mirror of
https://github.com/expo/eas-cli.git
synced 2026-11-15 03:38:08 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf27ec5238 | ||
|
|
8f18b35fe8 | ||
|
|
e82b8966b0 | ||
|
|
fad19a1e03 | ||
|
|
553d648e86 | ||
|
|
5588a7343d | ||
|
|
8ec3c52be8 | ||
|
|
e29d7916b8 | ||
|
|
b9840556fc | ||
|
|
3cfb6725e7 | ||
|
|
de794c37f4 | ||
|
|
c9a0747762 | ||
|
|
80dfcdbe29 | ||
|
|
6b05dd6226 |
No files matched your search
@@ -0,0 +1,29 @@
|
||||
name: Ensure GraphQL schema and generated code is up-to-date
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
- .github/workflows/test-graphql.yml
|
||||
- packages/eas-cli/src/**
|
||||
schedule:
|
||||
- cron: '0 8 * * *' # 8:00 AM UTC time every day
|
||||
|
||||
concurrency:
|
||||
group: test-graphql-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 22
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: yarn verify-graphql-code
|
||||
working-directory: packages/eas-cli
|
||||
+28
-1
@@ -8,10 +8,37 @@ This is the log of notable changes to EAS CLI and related packages.
|
||||
|
||||
### 🎉 New features
|
||||
|
||||
- Add update:revert-update-rollout command. ([#3068](https://github.com/expo/eas-cli/pull/3068) by [@wschurman](https://github.com/wschurman))
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
- Remove unreleased `link` and `unlink` commands from `eas env`. ([#3092](https://github.com/expo/eas-cli/pull/3092) by [@kadikraman](https://github.com/kadikraman))
|
||||
- Add new CI to verify GraphQL generation. ([#3093](https://github.com/expo/eas-cli/pull/3093) by [@douglowder](https://github.com/douglowder))
|
||||
- Update GraphQL generation to look in all src directories. ([#3097](https://github.com/expo/eas-cli/pull/3097) by [@wschurman](https://github.com/wschurman))
|
||||
|
||||
## [16.13.4](https://github.com/expo/eas-cli/releases/tag/v16.13.4) - 2025-07-04
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
- Remove hidden flag from `eas upload`. ([#3014](https://github.com/expo/eas-cli/pull/3014) by [@gabrieldonadel](https://github.com/gabrieldonadel))
|
||||
|
||||
## [16.13.3](https://github.com/expo/eas-cli/releases/tag/v16.13.3) - 2025-07-01
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
- Fix suggested command to switch Xcode Developer Tools. ([#3079](https://github.com/expo/eas-cli/pull/3079) by [@rolfb](https://github.com/rolfb))
|
||||
- Skip configuring build profiles when running `eas update:configure` if no build profiles exist. ([#3084](https://github.com/expo/eas-cli/pull/3084) by [@brentvatne](https://github.com/brentvatne))
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
- Reword how paid plans are described ([#3082](https://github.com/expo/eas-cli/pull/3082) by [@ide](https://github.com/ide))
|
||||
|
||||
## [16.13.2](https://github.com/expo/eas-cli/releases/tag/v16.13.2) - 2025-06-27
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
- Amend update override fields. ([#3080](https://github.com/expo/eas-cli/pull/3080) by [@quinlanj](https://github.com/quinlanj))
|
||||
|
||||
## [16.13.1](https://github.com/expo/eas-cli/releases/tag/v16.13.1) - 2025-06-25
|
||||
@@ -19,7 +46,7 @@ This is the log of notable changes to EAS CLI and related packages.
|
||||
### 🐛 Bug fixes
|
||||
|
||||
- Fix bug in log during update:republish. ([#3067](https://github.com/expo/eas-cli/pull/3067) by [@wschurman](https://github.com/wschurman))
|
||||
Fix update group deletion. ([#3069](https://github.com/expo/eas-cli/pull/3069) by [@wschurman](https://github.com/wschurman))
|
||||
- Fix update group deletion. ([#3069](https://github.com/expo/eas-cli/pull/3069) by [@wschurman](https://github.com/wschurman))
|
||||
|
||||
## [16.13.0](https://github.com/expo/eas-cli/releases/tag/v16.13.0) - 2025-06-24
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"npmClient": "yarn",
|
||||
"version": "16.13.2",
|
||||
"version": "16.14.0",
|
||||
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
|
||||
}
|
||||
+128
-78
@@ -129,9 +129,11 @@ eas --help COMMAND
|
||||
* [`eas update:edit [GROUPID]`](#eas-updateedit-groupid)
|
||||
* [`eas update:list`](#eas-updatelist)
|
||||
* [`eas update:republish`](#eas-updaterepublish)
|
||||
* [`eas update:revert-update-rollout`](#eas-updaterevert-update-rollout)
|
||||
* [`eas update:roll-back-to-embedded`](#eas-updateroll-back-to-embedded)
|
||||
* [`eas update:rollback`](#eas-updaterollback)
|
||||
* [`eas update:view GROUPID`](#eas-updateview-groupid)
|
||||
* [`eas upload`](#eas-upload)
|
||||
* [`eas webhook:create`](#eas-webhookcreate)
|
||||
* [`eas webhook:delete [ID]`](#eas-webhookdelete-id)
|
||||
* [`eas webhook:list`](#eas-webhooklist)
|
||||
@@ -164,7 +166,7 @@ ALIASES
|
||||
$ eas login
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/account/login.ts)_
|
||||
|
||||
## `eas account:logout`
|
||||
|
||||
@@ -181,7 +183,7 @@ ALIASES
|
||||
$ eas logout
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/account/logout.ts)_
|
||||
|
||||
## `eas account:view`
|
||||
|
||||
@@ -198,7 +200,7 @@ ALIASES
|
||||
$ eas whoami
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/account/view.ts)_
|
||||
|
||||
## `eas analytics [STATUS]`
|
||||
|
||||
@@ -212,7 +214,7 @@ DESCRIPTION
|
||||
display or change analytics settings
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/analytics.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/analytics.ts)_
|
||||
|
||||
## `eas autocomplete [SHELL]`
|
||||
|
||||
@@ -264,7 +266,7 @@ DESCRIPTION
|
||||
create a branch
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/branch/create.ts)_
|
||||
|
||||
## `eas branch:delete [NAME]`
|
||||
|
||||
@@ -285,7 +287,7 @@ DESCRIPTION
|
||||
delete a branch
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/branch/delete.ts)_
|
||||
|
||||
## `eas branch:list`
|
||||
|
||||
@@ -305,7 +307,7 @@ DESCRIPTION
|
||||
list all branches
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/branch/list.ts)_
|
||||
|
||||
## `eas branch:rename`
|
||||
|
||||
@@ -325,7 +327,7 @@ DESCRIPTION
|
||||
rename a branch
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/branch/rename.ts)_
|
||||
|
||||
## `eas branch:view [NAME]`
|
||||
|
||||
@@ -348,7 +350,7 @@ DESCRIPTION
|
||||
view a branch
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/branch/view.ts)_
|
||||
|
||||
## `eas build`
|
||||
|
||||
@@ -389,7 +391,7 @@ DESCRIPTION
|
||||
start a build
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/build/index.ts)_
|
||||
|
||||
## `eas build:cancel [BUILD_ID]`
|
||||
|
||||
@@ -408,7 +410,7 @@ DESCRIPTION
|
||||
cancel a build
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/build/cancel.ts)_
|
||||
|
||||
## `eas build:configure`
|
||||
|
||||
@@ -425,7 +427,7 @@ DESCRIPTION
|
||||
configure the project to support EAS Build
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/build/configure.ts)_
|
||||
|
||||
## `eas build:delete [BUILD_ID]`
|
||||
|
||||
@@ -444,7 +446,7 @@ DESCRIPTION
|
||||
delete a build
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/delete.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/build/delete.ts)_
|
||||
|
||||
## `eas build:dev`
|
||||
|
||||
@@ -464,7 +466,7 @@ DESCRIPTION
|
||||
run dev client simulator/emulator build with matching fingerprint or create a new one
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/dev.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/build/dev.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/build/dev.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/build/dev.ts)_
|
||||
|
||||
## `eas build:download`
|
||||
|
||||
@@ -485,7 +487,7 @@ DESCRIPTION
|
||||
download simulator/emulator builds for a given fingerprint hash
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/download.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/build/download.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/build/download.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/build/download.ts)_
|
||||
|
||||
## `eas build:inspect`
|
||||
|
||||
@@ -520,7 +522,7 @@ DESCRIPTION
|
||||
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/v16.13.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/v16.14.0/packages/eas-cli/src/commands/build/inspect.ts)_
|
||||
|
||||
## `eas build:list`
|
||||
|
||||
@@ -572,7 +574,7 @@ DESCRIPTION
|
||||
list all builds for your project
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/build/list.ts)_
|
||||
|
||||
## `eas build:resign`
|
||||
|
||||
@@ -601,7 +603,7 @@ DESCRIPTION
|
||||
re-sign a build archive
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/build/resign.ts)_
|
||||
|
||||
## `eas build:run`
|
||||
|
||||
@@ -627,7 +629,7 @@ DESCRIPTION
|
||||
run simulator/emulator builds from eas-cli
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/build/run.ts)_
|
||||
|
||||
## `eas build:submit`
|
||||
|
||||
@@ -681,7 +683,7 @@ DESCRIPTION
|
||||
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/v16.13.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/v16.14.0/packages/eas-cli/src/commands/build/version/get.ts)_
|
||||
|
||||
## `eas build:version:set`
|
||||
|
||||
@@ -700,7 +702,7 @@ DESCRIPTION
|
||||
update version of an app
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/build/version/set.ts)_
|
||||
|
||||
## `eas build:version:sync`
|
||||
|
||||
@@ -719,7 +721,7 @@ DESCRIPTION
|
||||
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/v16.13.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/v16.14.0/packages/eas-cli/src/commands/build/version/sync.ts)_
|
||||
|
||||
## `eas build:view [BUILD_ID]`
|
||||
|
||||
@@ -736,7 +738,7 @@ DESCRIPTION
|
||||
view a build for your project
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/build/view.ts)_
|
||||
|
||||
## `eas channel:create [NAME]`
|
||||
|
||||
@@ -757,7 +759,7 @@ DESCRIPTION
|
||||
create a channel
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/channel/create.ts)_
|
||||
|
||||
## `eas channel:edit [NAME]`
|
||||
|
||||
@@ -779,7 +781,7 @@ DESCRIPTION
|
||||
point a channel at a new branch
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/channel/edit.ts)_
|
||||
|
||||
## `eas channel:list`
|
||||
|
||||
@@ -799,7 +801,7 @@ DESCRIPTION
|
||||
list all channels
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/channel/list.ts)_
|
||||
|
||||
## `eas channel:pause [NAME]`
|
||||
|
||||
@@ -821,7 +823,7 @@ DESCRIPTION
|
||||
pause a channel to stop it from sending updates
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/channel/pause.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/channel/pause.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/channel/pause.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/channel/pause.ts)_
|
||||
|
||||
## `eas channel:resume [NAME]`
|
||||
|
||||
@@ -843,7 +845,7 @@ DESCRIPTION
|
||||
resume a channel to start sending updates
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/channel/resume.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/channel/resume.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/channel/resume.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/channel/resume.ts)_
|
||||
|
||||
## `eas channel:rollout [CHANNEL]`
|
||||
|
||||
@@ -876,7 +878,7 @@ DESCRIPTION
|
||||
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/v16.13.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/v16.14.0/packages/eas-cli/src/commands/channel/rollout.ts)_
|
||||
|
||||
## `eas channel:view [NAME]`
|
||||
|
||||
@@ -899,7 +901,7 @@ DESCRIPTION
|
||||
view a channel
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/channel/view.ts)_
|
||||
|
||||
## `eas config`
|
||||
|
||||
@@ -920,7 +922,7 @@ DESCRIPTION
|
||||
display project configuration (app.json + eas.json)
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/config.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/config.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/config.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/config.ts)_
|
||||
|
||||
## `eas credentials`
|
||||
|
||||
@@ -937,7 +939,7 @@ DESCRIPTION
|
||||
manage credentials
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/credentials/index.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/credentials/index.ts)_
|
||||
|
||||
## `eas credentials:configure-build`
|
||||
|
||||
@@ -955,7 +957,7 @@ DESCRIPTION
|
||||
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/v16.13.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/v16.14.0/packages/eas-cli/src/commands/credentials/configure-build.ts)_
|
||||
|
||||
## `eas deploy [2m[options][22m`
|
||||
|
||||
@@ -983,7 +985,7 @@ ALIASES
|
||||
$ eas worker:deploy
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/deploy/index.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/deploy/index.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/deploy/index.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/deploy/index.ts)_
|
||||
|
||||
## `eas deploy:alias`
|
||||
|
||||
@@ -1008,7 +1010,7 @@ ALIASES
|
||||
$ eas deploy:promote
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/deploy/alias.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/deploy/alias.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/deploy/alias.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/deploy/alias.ts)_
|
||||
|
||||
## `eas deploy:promote`
|
||||
|
||||
@@ -1045,7 +1047,7 @@ DESCRIPTION
|
||||
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/v16.13.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/v16.14.0/packages/eas-cli/src/commands/device/create.ts)_
|
||||
|
||||
## `eas device:delete`
|
||||
|
||||
@@ -1065,7 +1067,7 @@ DESCRIPTION
|
||||
remove a registered device from your account
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/device/delete.ts)_
|
||||
|
||||
## `eas device:list`
|
||||
|
||||
@@ -1086,7 +1088,7 @@ DESCRIPTION
|
||||
list all registered devices for your account
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/device/list.ts)_
|
||||
|
||||
## `eas device:rename`
|
||||
|
||||
@@ -1107,7 +1109,7 @@ DESCRIPTION
|
||||
rename a registered device
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/device/rename.ts)_
|
||||
|
||||
## `eas device:view [UDID]`
|
||||
|
||||
@@ -1121,7 +1123,7 @@ DESCRIPTION
|
||||
view a device for your project
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/device/view.ts)_
|
||||
|
||||
## `eas diagnostics`
|
||||
|
||||
@@ -1135,7 +1137,7 @@ DESCRIPTION
|
||||
display environment info
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/diagnostics.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/diagnostics.ts)_
|
||||
|
||||
## `eas env:create [ENVIRONMENT]`
|
||||
|
||||
@@ -1164,7 +1166,7 @@ DESCRIPTION
|
||||
create an environment variable for the current project or account
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/env/create.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/env/create.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/env/create.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/env/create.ts)_
|
||||
|
||||
## `eas env:delete [ENVIRONMENT]`
|
||||
|
||||
@@ -1188,7 +1190,7 @@ DESCRIPTION
|
||||
delete an environment variable for the current project or account
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/env/delete.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/env/delete.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/env/delete.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/env/delete.ts)_
|
||||
|
||||
## `eas env:exec ENVIRONMENT BASH_COMMAND`
|
||||
|
||||
@@ -1209,7 +1211,7 @@ DESCRIPTION
|
||||
execute a command with environment variables from the selected environment
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/env/exec.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/env/exec.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/env/exec.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/env/exec.ts)_
|
||||
|
||||
## `eas env:get [ENVIRONMENT]`
|
||||
|
||||
@@ -1234,7 +1236,7 @@ DESCRIPTION
|
||||
view an environment variable for the current project or account
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/env/get.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/env/get.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/env/get.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/env/get.ts)_
|
||||
|
||||
## `eas env:list [ENVIRONMENT]`
|
||||
|
||||
@@ -1259,7 +1261,7 @@ DESCRIPTION
|
||||
list environment variables for the current project or account
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/env/list.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/env/list.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/env/list.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/env/list.ts)_
|
||||
|
||||
## `eas env:pull [ENVIRONMENT]`
|
||||
|
||||
@@ -1282,7 +1284,7 @@ DESCRIPTION
|
||||
pull environment variables for the selected environment to .env file
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/env/pull.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/env/pull.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/env/pull.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/env/pull.ts)_
|
||||
|
||||
## `eas env:push [ENVIRONMENT]`
|
||||
|
||||
@@ -1303,7 +1305,7 @@ DESCRIPTION
|
||||
push environment variables from .env file to the selected environment
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/env/push.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/env/push.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/env/push.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/env/push.ts)_
|
||||
|
||||
## `eas env:update [ENVIRONMENT]`
|
||||
|
||||
@@ -1334,7 +1336,7 @@ DESCRIPTION
|
||||
update an environment variable on the current project or account
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/env/update.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/env/update.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/env/update.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/env/update.ts)_
|
||||
|
||||
## `eas fingerprint:compare [HASH1] [HASH2]`
|
||||
|
||||
@@ -1379,7 +1381,7 @@ EXAMPLES
|
||||
$ eas fingerprint:compare <FINGERPRINT-HASH> --update-id <UPDATE-ID> # Compare fingerprint from update against provided fingerprint
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/fingerprint/compare.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/fingerprint/compare.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/fingerprint/compare.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/fingerprint/compare.ts)_
|
||||
|
||||
## `eas fingerprint:generate`
|
||||
|
||||
@@ -1410,7 +1412,7 @@ EXAMPLES
|
||||
$ eas fingerprint:generate --json --non-interactive --platform android # Output fingerprint json to stdout
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/fingerprint/generate.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/fingerprint/generate.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/fingerprint/generate.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/fingerprint/generate.ts)_
|
||||
|
||||
## `eas help [COMMAND]`
|
||||
|
||||
@@ -1518,7 +1520,7 @@ DESCRIPTION
|
||||
validate the local store configuration
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/metadata/lint.ts)_
|
||||
|
||||
## `eas metadata:pull`
|
||||
|
||||
@@ -1535,7 +1537,7 @@ DESCRIPTION
|
||||
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/v16.13.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/v16.14.0/packages/eas-cli/src/commands/metadata/pull.ts)_
|
||||
|
||||
## `eas metadata:push`
|
||||
|
||||
@@ -1552,7 +1554,7 @@ DESCRIPTION
|
||||
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/v16.13.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/v16.14.0/packages/eas-cli/src/commands/metadata/push.ts)_
|
||||
|
||||
## `eas onboarding [TARGET_PROJECT_DIRECTORY]`
|
||||
|
||||
@@ -1582,7 +1584,7 @@ DESCRIPTION
|
||||
open the project page in a web browser
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/open.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/open.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/open.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/open.ts)_
|
||||
|
||||
## `eas project:info`
|
||||
|
||||
@@ -1596,7 +1598,7 @@ DESCRIPTION
|
||||
information about the current project
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/project/info.ts)_
|
||||
|
||||
## `eas project:init`
|
||||
|
||||
@@ -1619,7 +1621,7 @@ ALIASES
|
||||
$ eas init
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/project/init.ts)_
|
||||
|
||||
## `eas project:onboarding [TARGET_PROJECT_DIRECTORY]`
|
||||
|
||||
@@ -1637,7 +1639,7 @@ ALIASES
|
||||
$ eas onboarding
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/project/onboarding.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/project/onboarding.ts)_
|
||||
|
||||
## `eas submit`
|
||||
|
||||
@@ -1672,7 +1674,7 @@ ALIASES
|
||||
$ eas build:submit
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/submit.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/submit.ts)_
|
||||
|
||||
## `eas update`
|
||||
|
||||
@@ -1714,7 +1716,7 @@ DESCRIPTION
|
||||
publish an update group
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/update/index.ts)_
|
||||
|
||||
## `eas update:configure`
|
||||
|
||||
@@ -1734,7 +1736,7 @@ DESCRIPTION
|
||||
configure the project to support EAS Update
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/update/configure.ts)_
|
||||
|
||||
## `eas update:delete GROUPID`
|
||||
|
||||
@@ -1755,7 +1757,7 @@ DESCRIPTION
|
||||
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/v16.13.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/v16.14.0/packages/eas-cli/src/commands/update/delete.ts)_
|
||||
|
||||
## `eas update:edit [GROUPID]`
|
||||
|
||||
@@ -1779,7 +1781,7 @@ DESCRIPTION
|
||||
edit all the updates in an update group
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/update/edit.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/update/edit.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/update/edit.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/update/edit.ts)_
|
||||
|
||||
## `eas update:list`
|
||||
|
||||
@@ -1801,7 +1803,7 @@ DESCRIPTION
|
||||
view the recent updates
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/update/list.ts)_
|
||||
|
||||
## `eas update:republish`
|
||||
|
||||
@@ -1837,7 +1839,34 @@ DESCRIPTION
|
||||
roll back to an existing update
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/update/republish.ts)_
|
||||
|
||||
## `eas update:revert-update-rollout`
|
||||
|
||||
revert a rollout update for a project
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas update:revert-update-rollout [--channel <value> | --branch <value> | --group <value>] [-m <value>] [--private-key-path
|
||||
<value>] [--json --non-interactive]
|
||||
|
||||
FLAGS
|
||||
-m, --message=<value> Short message describing the revert
|
||||
--branch=<value> Branch name to select an update group to revert the rollout update from
|
||||
--channel=<value> Channel name to select an update group to revert the rollout update from
|
||||
--group=<value> Rollout update group ID to revert
|
||||
--json Enable JSON output, non-JSON messages will be printed to stderr.
|
||||
--non-interactive Run the command in non-interactive mode.
|
||||
--private-key-path=<value> File containing the PEM-encoded private key corresponding to the certificate in
|
||||
expo-updates' configuration. Defaults to a file named "private-key.pem" in the
|
||||
certificate's directory. Only relevant if you are using code signing:
|
||||
https://docs.expo.dev/eas-update/code-signing/
|
||||
|
||||
DESCRIPTION
|
||||
revert a rollout update for a project
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/update/revert-update-rollout.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/update/revert-update-rollout.ts)_
|
||||
|
||||
## `eas update:roll-back-to-embedded`
|
||||
|
||||
@@ -1865,7 +1894,7 @@ DESCRIPTION
|
||||
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/v16.13.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/v16.14.0/packages/eas-cli/src/commands/update/roll-back-to-embedded.ts)_
|
||||
|
||||
## `eas update:rollback`
|
||||
|
||||
@@ -1885,7 +1914,7 @@ DESCRIPTION
|
||||
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/v16.13.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/v16.14.0/packages/eas-cli/src/commands/update/rollback.ts)_
|
||||
|
||||
## `eas update:view GROUPID`
|
||||
|
||||
@@ -1905,7 +1934,28 @@ DESCRIPTION
|
||||
update group details
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/update/view.ts)_
|
||||
|
||||
## `eas upload`
|
||||
|
||||
upload a local build and generate a sharable link
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas upload [-p ios|android] [--build-path <value>] [--fingerprint <value>] [--json --non-interactive]
|
||||
|
||||
FLAGS
|
||||
-p, --platform=(ios|android)
|
||||
--build-path=<value> Path for the local build
|
||||
--fingerprint=<value> Fingerprint hash of the local build
|
||||
--json Enable JSON output, non-JSON messages will be printed to stderr.
|
||||
--non-interactive Run the command in non-interactive mode.
|
||||
|
||||
DESCRIPTION
|
||||
upload a local build and generate a sharable link
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/upload.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/upload.ts)_
|
||||
|
||||
## `eas webhook:create`
|
||||
|
||||
@@ -1926,7 +1976,7 @@ DESCRIPTION
|
||||
create a webhook
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/webhook/create.ts)_
|
||||
|
||||
## `eas webhook:delete [ID]`
|
||||
|
||||
@@ -1946,7 +1996,7 @@ DESCRIPTION
|
||||
delete a webhook
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/webhook/delete.ts)_
|
||||
|
||||
## `eas webhook:list`
|
||||
|
||||
@@ -1964,7 +2014,7 @@ DESCRIPTION
|
||||
list webhooks
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/webhook/list.ts)_
|
||||
|
||||
## `eas webhook:update`
|
||||
|
||||
@@ -1986,7 +2036,7 @@ DESCRIPTION
|
||||
update a webhook
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/webhook/update.ts)_
|
||||
|
||||
## `eas webhook:view ID`
|
||||
|
||||
@@ -2003,7 +2053,7 @@ DESCRIPTION
|
||||
view a webhook
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v16.13.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/v16.14.0/packages/eas-cli/src/commands/webhook/view.ts)_
|
||||
|
||||
## `eas whoami`
|
||||
|
||||
@@ -2085,7 +2135,7 @@ DESCRIPTION
|
||||
to cancel.
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/workflow/cancel.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/workflow/cancel.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/workflow/cancel.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/workflow/cancel.ts)_
|
||||
|
||||
## `eas workflow:create [NAME]`
|
||||
|
||||
@@ -2105,7 +2155,7 @@ DESCRIPTION
|
||||
create a new workflow configuration YAML file
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/workflow/create.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/workflow/create.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/workflow/create.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/workflow/create.ts)_
|
||||
|
||||
## `eas workflow:run [FILE]`
|
||||
|
||||
@@ -2132,7 +2182,7 @@ FLAG DESCRIPTIONS
|
||||
Exit codes: 0 = success, 11 = failure, 12 = canceled, 13 = wait aborted.
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/workflow/run.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/workflow/run.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/workflow/run.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/workflow/run.ts)_
|
||||
|
||||
## `eas workflow:runs`
|
||||
|
||||
@@ -2157,7 +2207,7 @@ DESCRIPTION
|
||||
list recent workflow runs for this project, with their IDs, statuses, and timestamps
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/workflow/runs.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/workflow/runs.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/workflow/runs.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/workflow/runs.ts)_
|
||||
|
||||
## `eas workflow:validate PATH`
|
||||
|
||||
@@ -2177,5 +2227,5 @@ DESCRIPTION
|
||||
validate a workflow configuration yaml file
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/workflow/validate.ts](https://github.com/expo/eas-cli/blob/v16.13.2/packages/eas-cli/src/commands/workflow/validate.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/workflow/validate.ts](https://github.com/expo/eas-cli/blob/v16.14.0/packages/eas-cli/src/commands/workflow/validate.ts)_
|
||||
<!-- commandsstop -->
|
||||
@@ -1,13 +1,7 @@
|
||||
overwrite: true
|
||||
schema: 'https://staging-api.expo.dev/graphql'
|
||||
documents:
|
||||
- 'src/graphql/**/!(*.d).{ts,tsx}'
|
||||
- 'src/credentials/ios/api/graphql/**/!(*.d).{ts,tsx}'
|
||||
- 'src/credentials/android/api/graphql/**/!(*.d).{ts,tsx}'
|
||||
- 'src/commands/**/*.ts'
|
||||
- 'src/branch/**/*.ts'
|
||||
- 'src/channel/**/*.ts'
|
||||
- 'src/worker/**/*.ts'
|
||||
- 'src/**/!(*.d).ts'
|
||||
generates:
|
||||
src/graphql/generated.ts:
|
||||
plugins:
|
||||
|
||||
Generated
+257
-337
@@ -309,6 +309,43 @@
|
||||
"isDeprecated": true,
|
||||
"deprecationReason": "Legacy access tokens are deprecated"
|
||||
},
|
||||
{
|
||||
"name": "accountFeatureGates",
|
||||
"description": "Server account feature gate values for this account, optionally filtering by desired gates.",
|
||||
"args": [
|
||||
{
|
||||
"name": "filter",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "JSONObject",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "activityTimelineProjectActivities",
|
||||
"description": "Coalesced project activity for all apps belonging to this account.",
|
||||
@@ -1360,103 +1397,6 @@
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "builds",
|
||||
"description": "(EAS Build) Builds associated with this account",
|
||||
"args": [
|
||||
{
|
||||
"name": "limit",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Int",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "offset",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Int",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "platform",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "ENUM",
|
||||
"name": "AppPlatform",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "status",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "ENUM",
|
||||
"name": "BuildStatus",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "Build",
|
||||
"ofType": null
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "canEnableSSO",
|
||||
"description": "Whether this account can enable SSO.",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Boolean",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "createdAt",
|
||||
"description": null,
|
||||
@@ -16069,6 +16009,50 @@
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "AppleDistributionCertificateQuery",
|
||||
"description": null,
|
||||
"fields": [
|
||||
{
|
||||
"name": "byId",
|
||||
"description": null,
|
||||
"args": [
|
||||
{
|
||||
"name": "id",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "ID",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "AppleDistributionCertificate",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "AppleProvisioningProfile",
|
||||
@@ -16514,6 +16498,50 @@
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "AppleProvisioningProfileQuery",
|
||||
"description": null,
|
||||
"fields": [
|
||||
{
|
||||
"name": "byId",
|
||||
"description": null,
|
||||
"args": [
|
||||
{
|
||||
"name": "id",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "ID",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "AppleProvisioningProfile",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "ApplePushKey",
|
||||
@@ -19630,18 +19658,6 @@
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "initiatingUser",
|
||||
"description": null,
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "User",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": true,
|
||||
"deprecationReason": "User type is deprecated"
|
||||
},
|
||||
{
|
||||
"name": "iosEnterpriseProvisioning",
|
||||
"description": null,
|
||||
@@ -20276,6 +20292,22 @@
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"description": null,
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "ENUM",
|
||||
"name": "BuildAnnotationType",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
@@ -20388,6 +20420,22 @@
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "ENUM",
|
||||
"name": "BuildAnnotationType",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"interfaces": null,
|
||||
@@ -20555,6 +20603,35 @@
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "ENUM",
|
||||
"name": "BuildAnnotationType",
|
||||
"description": null,
|
||||
"fields": null,
|
||||
"inputFields": null,
|
||||
"interfaces": null,
|
||||
"enumValues": [
|
||||
{
|
||||
"name": "ERROR",
|
||||
"description": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "INFO",
|
||||
"description": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "WARNING",
|
||||
"description": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "BuildAnnotationsQuery",
|
||||
@@ -28776,8 +28853,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
"isDeprecated": true,
|
||||
"deprecationReason": "Environment variables are automatically linked to all apps"
|
||||
},
|
||||
{
|
||||
"name": "createdAt",
|
||||
@@ -29351,177 +29428,6 @@
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "linkBulkSharedEnvironmentVariables",
|
||||
"description": "Bulk link shared environment variables",
|
||||
"args": [
|
||||
{
|
||||
"name": "linkData",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "INPUT_OBJECT",
|
||||
"name": "LinkSharedEnvironmentVariableInput",
|
||||
"ofType": null
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "EnvironmentVariable",
|
||||
"ofType": null
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "linkSharedEnvironmentVariable",
|
||||
"description": "Link shared environment variable",
|
||||
"args": [
|
||||
{
|
||||
"name": "appId",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "ID",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "environment",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "ENUM",
|
||||
"name": "EnvironmentVariableEnvironment",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "environmentVariableId",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "ID",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "EnvironmentVariable",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "unlinkSharedEnvironmentVariable",
|
||||
"description": "Unlink shared environment variable",
|
||||
"args": [
|
||||
{
|
||||
"name": "appId",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "ID",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "environment",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "ENUM",
|
||||
"name": "EnvironmentVariableEnvironment",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "environmentVariableId",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "ID",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "EnvironmentVariable",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "updateBulkEnvironmentVariables",
|
||||
"description": "Bulk update environment variables",
|
||||
@@ -38259,61 +38165,6 @@
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "INPUT_OBJECT",
|
||||
"name": "LinkSharedEnvironmentVariableInput",
|
||||
"description": null,
|
||||
"fields": null,
|
||||
"inputFields": [
|
||||
{
|
||||
"name": "appId",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "ID",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "environment",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "ENUM",
|
||||
"name": "EnvironmentVariableEnvironment",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "environmentVariableId",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "ID",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"interfaces": null,
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "INPUT_OBJECT",
|
||||
"name": "LocalBuildArchiveSourceInput",
|
||||
@@ -44122,6 +43973,30 @@
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "appleDistributionCertificate",
|
||||
"description": "Top-level query object for querying Apple distribution certificates.",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "AppleDistributionCertificateQuery",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "appleProvisioningProfile",
|
||||
"description": "Top-level query object for querying Apple provisioning profiles.",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "AppleProvisioningProfileQuery",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "appleTeam",
|
||||
"description": "Top-level query object for querying Apple Teams.",
|
||||
@@ -47714,6 +47589,12 @@
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "EAS_WORKFLOWS",
|
||||
"description": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "GITHUB_API_REQUESTS",
|
||||
"description": null,
|
||||
@@ -61902,6 +61783,22 @@
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "storageType",
|
||||
"description": null,
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "ENUM",
|
||||
"name": "WorkflowArtifactStorageType",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "updatedAt",
|
||||
"description": null,
|
||||
@@ -61924,6 +61821,29 @@
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "ENUM",
|
||||
"name": "WorkflowArtifactStorageType",
|
||||
"description": null,
|
||||
"fields": null,
|
||||
"inputFields": null,
|
||||
"interfaces": null,
|
||||
"enumValues": [
|
||||
{
|
||||
"name": "GCS",
|
||||
"description": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "R2",
|
||||
"description": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "WorkflowJob",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "eas-cli",
|
||||
"description": "EAS command line tool",
|
||||
"version": "16.13.2",
|
||||
"version": "16.14.0",
|
||||
"author": "Expo <[email protected]>",
|
||||
"bin": {
|
||||
"eas": "./bin/run"
|
||||
@@ -234,6 +234,7 @@
|
||||
"test": "jest",
|
||||
"version": "yarn oclif readme && node scripts/patch-readme && git add README.md",
|
||||
"generate-graphql-code": "graphql-codegen --config graphql-codegen.yml",
|
||||
"verify-graphql-code": "./scripts/verify-graphql.sh",
|
||||
"clean": "rimraf dist build tmp node_modules yarn-error.log"
|
||||
},
|
||||
"volta": {
|
||||
|
||||
Executable
+32
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
function cleanup()
|
||||
{
|
||||
echo 'Cleaning up...'
|
||||
rm -f graphql.schema.json.bak src/graphql/generated.ts.bak
|
||||
}
|
||||
|
||||
# Fail if anything errors
|
||||
set -eox pipefail
|
||||
# If this script exits, trap it first and clean up
|
||||
trap cleanup EXIT
|
||||
|
||||
cp graphql.schema.json graphql.schema.json.bak
|
||||
cp src/graphql/generated.ts src/graphql/generated.ts.bak
|
||||
|
||||
yarn generate-graphql-code
|
||||
if cmp -s graphql.schema.json graphql.schema.json.bak; then
|
||||
echo "GraphQL schema is up-to-date"
|
||||
if cmp -s src/graphql/generated.ts src/graphql/generated.ts.bak; then
|
||||
echo "GraphQL generated code is up-to-date"
|
||||
exit 0
|
||||
else
|
||||
echo "GraphQL code has changed but has not been regenerated. Run `yarn generate-graphql-code` and commit the changes."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "GraphQL schema has changed on the server. Running `yarn tsc` to check for breaking changes..."
|
||||
yarn tsc
|
||||
# If there are no errors, then the schema is backwards compatible
|
||||
exit 0
|
||||
fi
|
||||
@@ -500,11 +500,7 @@ async function handleSingleBuildProgressAsync(
|
||||
if (build.priority !== BuildPriority.High) {
|
||||
Log.newLine();
|
||||
Log.log('Start builds sooner in the priority queue.');
|
||||
Log.log(
|
||||
`Sign up for EAS Production or Enterprise at ${link(
|
||||
formatAccountBillingUrl(accountName)
|
||||
)}`
|
||||
);
|
||||
Log.log(`Sign up for a paid plan at ${link(formatAccountBillingUrl(accountName))}`);
|
||||
}
|
||||
|
||||
Log.newLine();
|
||||
|
||||
@@ -289,7 +289,7 @@ describe(EnvCreate, () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('creates an account-wide variable and links it', async () => {
|
||||
it('creates an account-wide variable', async () => {
|
||||
const command = new EnvCreate(
|
||||
[
|
||||
'--name',
|
||||
@@ -302,7 +302,6 @@ describe(EnvCreate, () => {
|
||||
'development',
|
||||
'--scope',
|
||||
'account',
|
||||
'--link',
|
||||
],
|
||||
mockConfig
|
||||
);
|
||||
@@ -330,18 +329,6 @@ describe(EnvCreate, () => {
|
||||
},
|
||||
testAccountId
|
||||
);
|
||||
expect(EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync).toHaveBeenCalledWith(
|
||||
graphqlClient,
|
||||
'testId',
|
||||
testProjectId,
|
||||
EnvironmentVariableEnvironment.Production
|
||||
);
|
||||
expect(EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync).toHaveBeenCalledWith(
|
||||
graphqlClient,
|
||||
'testId',
|
||||
testProjectId,
|
||||
EnvironmentVariableEnvironment.Development
|
||||
);
|
||||
});
|
||||
|
||||
it('prompts for missing arguments', async () => {
|
||||
|
||||
@@ -1,271 +0,0 @@
|
||||
import { Config } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
|
||||
import { getMockAppFragment } from '../../../__tests__/commands/utils';
|
||||
import {
|
||||
EnvironmentVariableEnvironment,
|
||||
EnvironmentVariableScope,
|
||||
} from '../../../graphql/generated';
|
||||
import { EnvironmentVariableMutation } from '../../../graphql/mutations/EnvironmentVariableMutation';
|
||||
import { AppQuery } from '../../../graphql/queries/AppQuery';
|
||||
import { EnvironmentVariablesQuery } from '../../../graphql/queries/EnvironmentVariablesQuery';
|
||||
import Log from '../../../log';
|
||||
import { promptAsync, selectAsync, toggleConfirmAsync } from '../../../prompts';
|
||||
import EnvLink from '../link';
|
||||
|
||||
jest.mock('../../../graphql/queries/EnvironmentVariablesQuery');
|
||||
jest.mock('../../../graphql/mutations/EnvironmentVariableMutation');
|
||||
jest.mock('../../../prompts');
|
||||
jest.mock('../../../graphql/queries/AppQuery');
|
||||
jest.mock('../../../log');
|
||||
|
||||
describe(EnvLink, () => {
|
||||
const projectId = 'test-project-id';
|
||||
const variableId = '1';
|
||||
const graphqlClient = {};
|
||||
const mockConfig = {} as unknown as Config;
|
||||
const mockContext = {
|
||||
projectId,
|
||||
loggedIn: { graphqlClient },
|
||||
};
|
||||
|
||||
const successMessage = (env: EnvironmentVariableEnvironment): string =>
|
||||
`Linked variable ${chalk.bold('TEST_VARIABLE')} to project ${chalk.bold(
|
||||
'@testuser/testpp'
|
||||
)} in ${env.toLocaleLowerCase()}.`;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
jest.mocked(AppQuery.byIdAsync).mockImplementation(async () => getMockAppFragment());
|
||||
});
|
||||
|
||||
it('links an account-wide variable to the current project in non-interactive mode', async () => {
|
||||
const mockVariables = [
|
||||
{
|
||||
id: variableId,
|
||||
name: 'TEST_VARIABLE',
|
||||
scope: EnvironmentVariableScope.Shared,
|
||||
environments: [EnvironmentVariableEnvironment.Development],
|
||||
},
|
||||
];
|
||||
(EnvironmentVariablesQuery.sharedAsync as jest.Mock).mockResolvedValue(mockVariables);
|
||||
(EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync as jest.Mock).mockResolvedValue(
|
||||
mockVariables[0]
|
||||
);
|
||||
|
||||
const command = new EnvLink(
|
||||
['--variable-name', 'TEST_VARIABLE', '--non-interactive'],
|
||||
mockConfig
|
||||
);
|
||||
// @ts-expect-error
|
||||
jest.spyOn(command, 'getContextAsync').mockReturnValue(mockContext);
|
||||
await command.run();
|
||||
|
||||
expect(EnvironmentVariablesQuery.sharedAsync).toHaveBeenCalledWith(graphqlClient, {
|
||||
appId: projectId,
|
||||
filterNames: ['TEST_VARIABLE'],
|
||||
});
|
||||
expect(EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync).toHaveBeenCalledWith(
|
||||
graphqlClient,
|
||||
variableId,
|
||||
projectId
|
||||
);
|
||||
expect(Log.withTick).toHaveBeenCalledWith(
|
||||
successMessage(EnvironmentVariableEnvironment.Development)
|
||||
);
|
||||
});
|
||||
|
||||
it('links an account-wide variable to the current project to a specified environment', async () => {
|
||||
const mockVariables = [
|
||||
{
|
||||
id: variableId,
|
||||
name: 'TEST_VARIABLE',
|
||||
scope: EnvironmentVariableScope.Shared,
|
||||
environments: [EnvironmentVariableEnvironment.Development],
|
||||
},
|
||||
];
|
||||
(EnvironmentVariablesQuery.sharedAsync as jest.Mock).mockResolvedValue(mockVariables);
|
||||
(EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync as jest.Mock).mockResolvedValue(
|
||||
mockVariables[0]
|
||||
);
|
||||
|
||||
const command = new EnvLink(
|
||||
['--variable-name', 'TEST_VARIABLE', '--environment', 'production', '--non-interactive'],
|
||||
mockConfig
|
||||
);
|
||||
// @ts-expect-error
|
||||
jest.spyOn(command, 'getContextAsync').mockReturnValue(mockContext);
|
||||
await command.run();
|
||||
|
||||
expect(EnvironmentVariablesQuery.sharedAsync).toHaveBeenCalledWith(graphqlClient, {
|
||||
appId: projectId,
|
||||
filterNames: ['TEST_VARIABLE'],
|
||||
});
|
||||
expect(EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync).toHaveBeenCalledWith(
|
||||
graphqlClient,
|
||||
variableId,
|
||||
projectId,
|
||||
EnvironmentVariableEnvironment.Production
|
||||
);
|
||||
expect(Log.withTick).toHaveBeenCalledWith(
|
||||
successMessage(EnvironmentVariableEnvironment.Production)
|
||||
);
|
||||
});
|
||||
|
||||
it('uses --variable-environment to select the variable with ambigous name', async () => {
|
||||
const mockVariables = [
|
||||
{
|
||||
id: variableId,
|
||||
name: 'TEST_VARIABLE',
|
||||
scope: EnvironmentVariableScope.Shared,
|
||||
environments: [EnvironmentVariableEnvironment.Preview],
|
||||
},
|
||||
{
|
||||
id: 'other-id',
|
||||
name: 'TEST_VARIABLE',
|
||||
scope: EnvironmentVariableScope.Shared,
|
||||
environments: [EnvironmentVariableEnvironment.Development],
|
||||
},
|
||||
];
|
||||
(EnvironmentVariablesQuery.sharedAsync as jest.Mock).mockImplementation(
|
||||
(_client, { environment }) => {
|
||||
return mockVariables.filter(v => v.environments.includes(environment));
|
||||
}
|
||||
);
|
||||
(EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync as jest.Mock).mockResolvedValue(
|
||||
mockVariables[0]
|
||||
);
|
||||
(toggleConfirmAsync as jest.Mock).mockResolvedValue(true);
|
||||
|
||||
const command = new EnvLink(
|
||||
[
|
||||
'--variable-name',
|
||||
'TEST_VARIABLE',
|
||||
'--variable-environment',
|
||||
'development',
|
||||
'--environment',
|
||||
'production',
|
||||
],
|
||||
mockConfig
|
||||
);
|
||||
// @ts-expect-error
|
||||
jest.spyOn(command, 'getContextAsync').mockReturnValue(mockContext);
|
||||
await command.runAsync();
|
||||
|
||||
expect(EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync).toHaveBeenCalledWith(
|
||||
graphqlClient,
|
||||
'other-id',
|
||||
projectId,
|
||||
EnvironmentVariableEnvironment.Production
|
||||
);
|
||||
expect(Log.withTick).toHaveBeenCalledWith(
|
||||
successMessage(EnvironmentVariableEnvironment.Production)
|
||||
);
|
||||
});
|
||||
|
||||
it('prompts for variable selection when the name is ambigous', async () => {
|
||||
const mockVariables = [
|
||||
{
|
||||
id: variableId,
|
||||
name: 'TEST_VARIABLE',
|
||||
scope: EnvironmentVariableScope.Shared,
|
||||
environments: [EnvironmentVariableEnvironment.Preview],
|
||||
},
|
||||
{
|
||||
id: 'other-id',
|
||||
name: 'TEST_VARIABLE',
|
||||
scope: EnvironmentVariableScope.Shared,
|
||||
environments: [EnvironmentVariableEnvironment.Development],
|
||||
},
|
||||
];
|
||||
(EnvironmentVariablesQuery.sharedAsync as jest.Mock).mockResolvedValue(mockVariables);
|
||||
(EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync as jest.Mock).mockResolvedValue(
|
||||
mockVariables[0]
|
||||
);
|
||||
(selectAsync as jest.Mock).mockResolvedValue(mockVariables[0]);
|
||||
(promptAsync as jest.Mock).mockResolvedValue({ environments: mockVariables[0].environments });
|
||||
(toggleConfirmAsync as jest.Mock).mockResolvedValue(true);
|
||||
|
||||
const command = new EnvLink([], mockConfig);
|
||||
// @ts-expect-error
|
||||
jest.spyOn(command, 'getContextAsync').mockReturnValue(mockContext);
|
||||
await command.runAsync();
|
||||
|
||||
expect(selectAsync).toHaveBeenCalled();
|
||||
expect(EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync).toHaveBeenCalledWith(
|
||||
graphqlClient,
|
||||
variableId,
|
||||
projectId,
|
||||
EnvironmentVariableEnvironment.Preview
|
||||
);
|
||||
expect(Log.withTick).toHaveBeenCalledWith(
|
||||
successMessage(EnvironmentVariableEnvironment.Preview)
|
||||
);
|
||||
});
|
||||
|
||||
it('throws an error when variable name is not found', async () => {
|
||||
const mockVariables: never[] = [];
|
||||
(EnvironmentVariablesQuery.sharedAsync as jest.Mock).mockResolvedValue(mockVariables);
|
||||
|
||||
const command = new EnvLink(['--variable-name', 'NON_EXISTENT_VARIABLE'], mockConfig);
|
||||
|
||||
// @ts-expect-error
|
||||
jest.spyOn(command, 'getContextAsync').mockReturnValue(mockContext);
|
||||
await expect(command.runAsync()).rejects.toThrow(
|
||||
"Account-wide variable NON_EXISTENT_VARIABLE doesn't exist"
|
||||
);
|
||||
});
|
||||
|
||||
it('uses environments from prompt to both link and unlink environments', async () => {
|
||||
const mockVariables = [
|
||||
{
|
||||
id: variableId,
|
||||
name: 'TEST_VARIABLE',
|
||||
scope: EnvironmentVariableScope.Shared,
|
||||
environments: [EnvironmentVariableEnvironment.Preview],
|
||||
linkedEnvironments: [EnvironmentVariableEnvironment.Preview],
|
||||
},
|
||||
];
|
||||
(EnvironmentVariablesQuery.sharedAsync as jest.Mock).mockResolvedValue(mockVariables);
|
||||
(EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync as jest.Mock).mockResolvedValue(
|
||||
mockVariables[0]
|
||||
);
|
||||
(selectAsync as jest.Mock).mockResolvedValue(mockVariables[0]);
|
||||
(promptAsync as jest.Mock).mockResolvedValue({
|
||||
environments: [EnvironmentVariableEnvironment.Production],
|
||||
});
|
||||
(toggleConfirmAsync as jest.Mock).mockResolvedValue(true);
|
||||
|
||||
const command = new EnvLink([], mockConfig);
|
||||
// @ts-expect-error
|
||||
jest.spyOn(command, 'getContextAsync').mockReturnValue(mockContext);
|
||||
await command.runAsync();
|
||||
|
||||
expect(promptAsync).toHaveBeenCalled();
|
||||
expect(EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync).toHaveBeenCalledWith(
|
||||
graphqlClient,
|
||||
variableId,
|
||||
projectId,
|
||||
EnvironmentVariableEnvironment.Production
|
||||
);
|
||||
expect(EnvironmentVariableMutation.unlinkSharedEnvironmentVariableAsync).toHaveBeenCalledWith(
|
||||
graphqlClient,
|
||||
variableId,
|
||||
projectId,
|
||||
EnvironmentVariableEnvironment.Preview
|
||||
);
|
||||
});
|
||||
|
||||
it('throws an error when variable name is not found', async () => {
|
||||
const mockVariables: never[] = [];
|
||||
(EnvironmentVariablesQuery.sharedAsync as jest.Mock).mockResolvedValue(mockVariables);
|
||||
|
||||
const command = new EnvLink(['--variable-name', 'NON_EXISTENT_VARIABLE'], mockConfig);
|
||||
|
||||
// @ts-expect-error
|
||||
jest.spyOn(command, 'getContextAsync').mockReturnValue(mockContext);
|
||||
await expect(command.runAsync()).rejects.toThrow(
|
||||
"Account-wide variable NON_EXISTENT_VARIABLE doesn't exist"
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,226 +0,0 @@
|
||||
import { Config } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
|
||||
import { getMockAppFragment } from '../../../__tests__/commands/utils';
|
||||
import {
|
||||
EnvironmentVariableEnvironment,
|
||||
EnvironmentVariableScope,
|
||||
} from '../../../graphql/generated';
|
||||
import { EnvironmentVariableMutation } from '../../../graphql/mutations/EnvironmentVariableMutation';
|
||||
import { AppQuery } from '../../../graphql/queries/AppQuery';
|
||||
import { EnvironmentVariablesQuery } from '../../../graphql/queries/EnvironmentVariablesQuery';
|
||||
import Log from '../../../log';
|
||||
import { promptAsync, selectAsync, toggleConfirmAsync } from '../../../prompts';
|
||||
import EnvUnlink from '../unlink';
|
||||
|
||||
jest.mock('../../../graphql/queries/EnvironmentVariablesQuery');
|
||||
jest.mock('../../../graphql/mutations/EnvironmentVariableMutation');
|
||||
jest.mock('../../../prompts');
|
||||
jest.mock('../../../graphql/queries/AppQuery');
|
||||
jest.mock('../../../log');
|
||||
|
||||
describe(EnvUnlink, () => {
|
||||
const projectId = 'test-project-id';
|
||||
const variableId = '1';
|
||||
const graphqlClient = {};
|
||||
const mockConfig = {} as unknown as Config;
|
||||
const mockContext = {
|
||||
projectId,
|
||||
loggedIn: { graphqlClient },
|
||||
};
|
||||
|
||||
const successMessage = (env: EnvironmentVariableEnvironment): string =>
|
||||
`Unlinked variable ${chalk.bold('TEST_VARIABLE')} from project ${chalk.bold(
|
||||
'@testuser/testpp'
|
||||
)} in ${env.toLocaleLowerCase()}.`;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
jest.mocked(AppQuery.byIdAsync).mockImplementation(async () => getMockAppFragment());
|
||||
});
|
||||
|
||||
it('unlinks an account-wide variable from the current project in non-interactive mode', async () => {
|
||||
const mockVariables = [
|
||||
{
|
||||
id: variableId,
|
||||
name: 'TEST_VARIABLE',
|
||||
scope: EnvironmentVariableScope.Shared,
|
||||
environments: [EnvironmentVariableEnvironment.Development],
|
||||
linkedEnvironments: [EnvironmentVariableEnvironment.Development],
|
||||
},
|
||||
];
|
||||
(EnvironmentVariablesQuery.sharedAsync as jest.Mock).mockResolvedValue(mockVariables);
|
||||
(
|
||||
EnvironmentVariableMutation.unlinkSharedEnvironmentVariableAsync as jest.Mock
|
||||
).mockResolvedValue(mockVariables[0]);
|
||||
|
||||
const command = new EnvUnlink(
|
||||
['--variable-name', 'TEST_VARIABLE', '--non-interactive'],
|
||||
mockConfig
|
||||
);
|
||||
// @ts-expect-error
|
||||
jest.spyOn(command, 'getContextAsync').mockReturnValue(mockContext);
|
||||
await command.run();
|
||||
|
||||
expect(EnvironmentVariablesQuery.sharedAsync).toHaveBeenCalledWith(graphqlClient, {
|
||||
appId: projectId,
|
||||
filterNames: ['TEST_VARIABLE'],
|
||||
});
|
||||
expect(EnvironmentVariableMutation.unlinkSharedEnvironmentVariableAsync).toHaveBeenCalledWith(
|
||||
graphqlClient,
|
||||
variableId,
|
||||
projectId
|
||||
);
|
||||
expect(Log.withTick).toHaveBeenCalledWith(
|
||||
successMessage(EnvironmentVariableEnvironment.Development)
|
||||
);
|
||||
});
|
||||
|
||||
it('unlinks an account-wide variable from the current project in a specified environment', async () => {
|
||||
const mockVariables = [
|
||||
{
|
||||
id: variableId,
|
||||
name: 'TEST_VARIABLE',
|
||||
scope: EnvironmentVariableScope.Shared,
|
||||
environments: [EnvironmentVariableEnvironment.Development],
|
||||
linkedEnvironments: [EnvironmentVariableEnvironment.Production],
|
||||
},
|
||||
];
|
||||
(EnvironmentVariablesQuery.sharedAsync as jest.Mock).mockResolvedValue(mockVariables);
|
||||
(
|
||||
EnvironmentVariableMutation.unlinkSharedEnvironmentVariableAsync as jest.Mock
|
||||
).mockResolvedValue(mockVariables[0]);
|
||||
|
||||
const command = new EnvUnlink(
|
||||
['--variable-name', 'TEST_VARIABLE', '--environment', 'production', '--non-interactive'],
|
||||
mockConfig
|
||||
);
|
||||
// @ts-expect-error
|
||||
jest.spyOn(command, 'getContextAsync').mockReturnValue(mockContext);
|
||||
await command.run();
|
||||
|
||||
expect(Log.withTick).toHaveBeenCalledWith(
|
||||
successMessage(EnvironmentVariableEnvironment.Production)
|
||||
);
|
||||
expect(EnvironmentVariablesQuery.sharedAsync).toHaveBeenCalledWith(graphqlClient, {
|
||||
appId: projectId,
|
||||
filterNames: ['TEST_VARIABLE'],
|
||||
});
|
||||
expect(EnvironmentVariableMutation.unlinkSharedEnvironmentVariableAsync).toHaveBeenCalledWith(
|
||||
graphqlClient,
|
||||
variableId,
|
||||
projectId,
|
||||
EnvironmentVariableEnvironment.Production
|
||||
);
|
||||
});
|
||||
|
||||
it('prompts for variable selection when the name is ambigous', async () => {
|
||||
const mockVariables = [
|
||||
{
|
||||
id: variableId,
|
||||
name: 'TEST_VARIABLE',
|
||||
scope: EnvironmentVariableScope.Shared,
|
||||
environments: [EnvironmentVariableEnvironment.Preview],
|
||||
linkedEnvironments: [EnvironmentVariableEnvironment.Preview],
|
||||
},
|
||||
{
|
||||
id: 'other-id',
|
||||
name: 'TEST_VARIABLE',
|
||||
scope: EnvironmentVariableScope.Shared,
|
||||
environments: [EnvironmentVariableEnvironment.Development],
|
||||
linkedEnvironments: [EnvironmentVariableEnvironment.Development],
|
||||
},
|
||||
];
|
||||
(EnvironmentVariablesQuery.sharedAsync as jest.Mock).mockResolvedValue(mockVariables);
|
||||
(
|
||||
EnvironmentVariableMutation.unlinkSharedEnvironmentVariableAsync as jest.Mock
|
||||
).mockResolvedValue(mockVariables[0]);
|
||||
(selectAsync as jest.Mock).mockResolvedValue(mockVariables[0]);
|
||||
(promptAsync as jest.Mock).mockResolvedValue({
|
||||
environments: [],
|
||||
});
|
||||
(toggleConfirmAsync as jest.Mock).mockResolvedValue(true);
|
||||
|
||||
const command = new EnvUnlink([], mockConfig);
|
||||
// @ts-expect-error
|
||||
jest.spyOn(command, 'getContextAsync').mockReturnValue(mockContext);
|
||||
await command.runAsync();
|
||||
|
||||
expect(selectAsync).toHaveBeenCalled();
|
||||
expect(EnvironmentVariableMutation.unlinkSharedEnvironmentVariableAsync).toHaveBeenCalledWith(
|
||||
graphqlClient,
|
||||
variableId,
|
||||
projectId,
|
||||
EnvironmentVariableEnvironment.Preview
|
||||
);
|
||||
expect(Log.withTick).toHaveBeenCalledWith(
|
||||
successMessage(EnvironmentVariableEnvironment.Preview)
|
||||
);
|
||||
});
|
||||
|
||||
it('throws an error when variable name is not found', async () => {
|
||||
const mockVariables: never[] = [];
|
||||
(EnvironmentVariablesQuery.sharedAsync as jest.Mock).mockResolvedValue(mockVariables);
|
||||
|
||||
const command = new EnvUnlink(['--variable-name', 'NON_EXISTENT_VARIABLE'], mockConfig);
|
||||
|
||||
// @ts-expect-error
|
||||
jest.spyOn(command, 'getContextAsync').mockReturnValue(mockContext);
|
||||
await expect(command.runAsync()).rejects.toThrow(
|
||||
"Account-wide variable NON_EXISTENT_VARIABLE doesn't exist"
|
||||
);
|
||||
});
|
||||
|
||||
it('uses environments from prompt to both link and unlink environments', async () => {
|
||||
const mockVariables = [
|
||||
{
|
||||
id: variableId,
|
||||
name: 'TEST_VARIABLE',
|
||||
scope: EnvironmentVariableScope.Shared,
|
||||
environments: [EnvironmentVariableEnvironment.Preview],
|
||||
linkedEnvironments: [EnvironmentVariableEnvironment.Preview],
|
||||
},
|
||||
];
|
||||
(EnvironmentVariablesQuery.sharedAsync as jest.Mock).mockResolvedValue(mockVariables);
|
||||
(EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync as jest.Mock).mockResolvedValue(
|
||||
mockVariables[0]
|
||||
);
|
||||
(selectAsync as jest.Mock).mockResolvedValue(mockVariables[0]);
|
||||
(promptAsync as jest.Mock).mockResolvedValue({
|
||||
environments: [EnvironmentVariableEnvironment.Production],
|
||||
});
|
||||
(toggleConfirmAsync as jest.Mock).mockResolvedValue(true);
|
||||
|
||||
const command = new EnvUnlink([], mockConfig);
|
||||
// @ts-expect-error
|
||||
jest.spyOn(command, 'getContextAsync').mockReturnValue(mockContext);
|
||||
await command.runAsync();
|
||||
|
||||
expect(promptAsync).toHaveBeenCalled();
|
||||
expect(EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync).toHaveBeenCalledWith(
|
||||
graphqlClient,
|
||||
variableId,
|
||||
projectId,
|
||||
EnvironmentVariableEnvironment.Production
|
||||
);
|
||||
expect(EnvironmentVariableMutation.unlinkSharedEnvironmentVariableAsync).toHaveBeenCalledWith(
|
||||
graphqlClient,
|
||||
variableId,
|
||||
projectId,
|
||||
EnvironmentVariableEnvironment.Preview
|
||||
);
|
||||
});
|
||||
|
||||
it('throws an error when variable name is not found', async () => {
|
||||
const mockVariables: never[] = [];
|
||||
(EnvironmentVariablesQuery.sharedAsync as jest.Mock).mockResolvedValue(mockVariables);
|
||||
|
||||
const command = new EnvUnlink(['--variable-name', 'NON_EXISTENT_VARIABLE'], mockConfig);
|
||||
|
||||
// @ts-expect-error
|
||||
jest.spyOn(command, 'getContextAsync').mockReturnValue(mockContext);
|
||||
await expect(command.runAsync()).rejects.toThrow(
|
||||
"Account-wide variable NON_EXISTENT_VARIABLE doesn't exist"
|
||||
);
|
||||
});
|
||||
});
|
||||
+1
-61
@@ -33,12 +33,11 @@ import {
|
||||
promptVariableValueAsync,
|
||||
promptVariableVisibilityAsync,
|
||||
} from '../../utils/prompts';
|
||||
import { isEnvironment, performForEnvironmentsAsync } from '../../utils/variableUtils';
|
||||
import { isEnvironment } from '../../utils/variableUtils';
|
||||
|
||||
interface RawCreateFlags {
|
||||
name?: string;
|
||||
value?: string;
|
||||
link?: boolean;
|
||||
force?: boolean;
|
||||
type?: 'string' | 'file';
|
||||
visibility?: 'plaintext' | 'sensitive' | 'secret';
|
||||
@@ -50,7 +49,6 @@ interface RawCreateFlags {
|
||||
interface CreateFlags {
|
||||
name?: string;
|
||||
value?: string;
|
||||
link?: boolean;
|
||||
force?: boolean;
|
||||
type?: 'string' | 'file';
|
||||
visibility?: 'plaintext' | 'sensitive' | 'secret';
|
||||
@@ -78,10 +76,6 @@ export default class EnvCreate extends EasCommand {
|
||||
value: Flags.string({
|
||||
description: 'Text value or the variable',
|
||||
}),
|
||||
link: Flags.boolean({
|
||||
description: 'Link account-wide variable to the current project',
|
||||
hidden: true, // every account-wide variable is global for now so it's not user facing
|
||||
}),
|
||||
force: Flags.boolean({
|
||||
description: 'Overwrite existing variable',
|
||||
default: false,
|
||||
@@ -114,7 +108,6 @@ export default class EnvCreate extends EasCommand {
|
||||
'non-interactive': nonInteractive,
|
||||
environment: environments,
|
||||
visibility,
|
||||
link,
|
||||
force,
|
||||
type,
|
||||
fileName,
|
||||
@@ -154,29 +147,6 @@ export default class EnvCreate extends EasCommand {
|
||||
});
|
||||
overwrite = true;
|
||||
}
|
||||
if (existingVariable.scope === EnvironmentVariableScope.Shared) {
|
||||
await this.promptForOverwriteAsync({
|
||||
nonInteractive,
|
||||
force,
|
||||
message: `Account-wide variable with ${name} name already exists on this account.`,
|
||||
suggestion: 'Do you want to unlink it first?',
|
||||
});
|
||||
|
||||
Log.withTick(
|
||||
`Unlinking account-wide variable ${chalk.bold(name)} on project ${chalk.bold(
|
||||
projectDisplayName
|
||||
)}.`
|
||||
);
|
||||
|
||||
await performForEnvironmentsAsync(environments, async environment => {
|
||||
await EnvironmentVariableMutation.unlinkSharedEnvironmentVariableAsync(
|
||||
graphqlClient,
|
||||
existingVariable.id,
|
||||
projectId,
|
||||
environment
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const variable =
|
||||
@@ -265,29 +235,6 @@ export default class EnvCreate extends EasCommand {
|
||||
Log.withTick(
|
||||
`Created a new variable ${chalk.bold(name)} on account ${chalk.bold(ownerAccount.name)}.`
|
||||
);
|
||||
|
||||
if (link) {
|
||||
Log.withTick(
|
||||
`Linking account-wide variable ${chalk.bold(name)} to project ${chalk.bold(
|
||||
projectDisplayName
|
||||
)}.`
|
||||
);
|
||||
|
||||
await performForEnvironmentsAsync(environments, async environment => {
|
||||
await EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync(
|
||||
graphqlClient,
|
||||
variable.id,
|
||||
projectId,
|
||||
environment
|
||||
);
|
||||
});
|
||||
|
||||
Log.withTick(
|
||||
`Linked account-wide variable ${chalk.bold(name)} to project ${chalk.bold(
|
||||
projectDisplayName
|
||||
)}.`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,7 +349,6 @@ export default class EnvCreate extends EasCommand {
|
||||
value,
|
||||
environment: newEnvironments,
|
||||
visibility: newVisibility,
|
||||
link: rest.link ?? false,
|
||||
force: rest.force ?? false,
|
||||
'non-interactive': nonInteractive,
|
||||
type: newType,
|
||||
@@ -412,12 +358,6 @@ export default class EnvCreate extends EasCommand {
|
||||
}
|
||||
|
||||
private sanitizeFlags(flags: RawCreateFlags): CreateFlags {
|
||||
if (flags.scope !== 'account' && flags.link) {
|
||||
throw new Error(
|
||||
`Unexpected argument: --link can only be used when creating account-wide variables`
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...flags,
|
||||
scope:
|
||||
|
||||
-204
@@ -1,204 +0,0 @@
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import {
|
||||
EASMultiEnvironmentFlag,
|
||||
EASNonInteractiveFlag,
|
||||
EasEnvironmentFlagParameters,
|
||||
} from '../../commandUtils/flags';
|
||||
import { EnvironmentVariableEnvironment } 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';
|
||||
import { formatVariableName, isEnvironment } from '../../utils/variableUtils';
|
||||
|
||||
type LinkFlags = {
|
||||
'variable-name'?: string;
|
||||
'variable-environment'?: EnvironmentVariableEnvironment;
|
||||
'non-interactive': boolean;
|
||||
environment?: EnvironmentVariableEnvironment[];
|
||||
};
|
||||
|
||||
export default class EnvLink extends EasCommand {
|
||||
static override description = 'link an account-wide environment variable to the current project';
|
||||
|
||||
// for now we only roll out global account-wide env variables so this should stay hidden
|
||||
static override hidden = true;
|
||||
|
||||
static override flags = {
|
||||
'variable-name': Flags.string({
|
||||
description: 'Name of the variable',
|
||||
}),
|
||||
'variable-environment': Flags.enum<EnvironmentVariableEnvironment>({
|
||||
...EasEnvironmentFlagParameters,
|
||||
description: 'Current environment of the variable to link',
|
||||
}),
|
||||
...EASMultiEnvironmentFlag,
|
||||
...EASNonInteractiveFlag,
|
||||
};
|
||||
|
||||
static override args = [
|
||||
{
|
||||
name: 'environment',
|
||||
description:
|
||||
"Environment to pull variables from. One of 'production', 'preview', or 'development'.",
|
||||
required: false,
|
||||
},
|
||||
];
|
||||
|
||||
static override contextDefinition = {
|
||||
...this.ContextOptions.ProjectId,
|
||||
...this.ContextOptions.LoggedIn,
|
||||
};
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { args, flags } = await this.parse(EnvLink);
|
||||
|
||||
let {
|
||||
'variable-name': name,
|
||||
'variable-environment': currentEnvironment,
|
||||
'non-interactive': nonInteractive,
|
||||
environment: environments,
|
||||
} = this.validateInputs(flags, args);
|
||||
|
||||
const {
|
||||
projectId,
|
||||
loggedIn: { graphqlClient },
|
||||
} = await this.getContextAsync(EnvLink, {
|
||||
nonInteractive,
|
||||
});
|
||||
|
||||
const projectDisplayName = await getDisplayNameForProjectIdAsync(graphqlClient, projectId);
|
||||
const variables = await EnvironmentVariablesQuery.sharedAsync(graphqlClient, {
|
||||
appId: projectId,
|
||||
environment: currentEnvironment,
|
||||
filterNames: name ? [name] : undefined,
|
||||
});
|
||||
|
||||
let selectedVariable = variables[0];
|
||||
|
||||
if (variables.length > 1) {
|
||||
if (nonInteractive) {
|
||||
throw new Error(
|
||||
'Multiple variables found, run command with --variable-name and --variable-environment arguments.'
|
||||
);
|
||||
}
|
||||
selectedVariable = await selectAsync(
|
||||
'Select account-wide variable',
|
||||
variables.map(variable => ({
|
||||
title: formatVariableName(variable),
|
||||
value: variable,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
if (!selectedVariable) {
|
||||
throw new Error(`Account-wide variable ${name} doesn't exist`);
|
||||
}
|
||||
|
||||
let explicitSelect = false;
|
||||
if (!nonInteractive && !environments) {
|
||||
const selectedEnvironments =
|
||||
(selectedVariable.linkedEnvironments ?? []).length > 0
|
||||
? selectedVariable.linkedEnvironments
|
||||
: selectedVariable.environments;
|
||||
environments = await promptVariableEnvironmentAsync({
|
||||
nonInteractive,
|
||||
multiple: true,
|
||||
selectedEnvironments: selectedEnvironments ?? [],
|
||||
});
|
||||
explicitSelect = true;
|
||||
}
|
||||
|
||||
if (!environments) {
|
||||
await EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync(
|
||||
graphqlClient,
|
||||
selectedVariable.id,
|
||||
projectId
|
||||
);
|
||||
Log.withTick(
|
||||
`Linked variable ${chalk.bold(selectedVariable.name)} to project ${chalk.bold(
|
||||
projectDisplayName
|
||||
)} in ${selectedVariable.environments?.join(', ').toLocaleLowerCase()}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const environment of Object.values(EnvironmentVariableEnvironment)) {
|
||||
try {
|
||||
if (
|
||||
selectedVariable.linkedEnvironments?.includes(environment) ===
|
||||
environments.includes(environment)
|
||||
) {
|
||||
if (!explicitSelect && environments.includes(environment)) {
|
||||
Log.withTick(
|
||||
`Variable ${chalk.bold(
|
||||
selectedVariable.name
|
||||
)} is already linked to ${environment.toLocaleLowerCase()}.`
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (environments.includes(environment)) {
|
||||
await EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync(
|
||||
graphqlClient,
|
||||
selectedVariable.id,
|
||||
projectId,
|
||||
environment
|
||||
);
|
||||
Log.withTick(
|
||||
`Linked variable ${chalk.bold(selectedVariable.name)} to project ${chalk.bold(
|
||||
projectDisplayName
|
||||
)} in ${environment.toLocaleLowerCase()}.`
|
||||
);
|
||||
} else if (explicitSelect) {
|
||||
await EnvironmentVariableMutation.unlinkSharedEnvironmentVariableAsync(
|
||||
graphqlClient,
|
||||
selectedVariable.id,
|
||||
projectId,
|
||||
environment
|
||||
);
|
||||
Log.withTick(
|
||||
`Unlinked variable ${chalk.bold(selectedVariable.name)} from project ${chalk.bold(
|
||||
projectDisplayName
|
||||
)} in ${environment.toLocaleLowerCase()}.`
|
||||
);
|
||||
}
|
||||
} catch (err: any) {
|
||||
Log.warn(err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
private validateInputs(flags: LinkFlags, { environment }: { environment?: string }): LinkFlags {
|
||||
environment = environment?.toUpperCase();
|
||||
|
||||
if (environment && !isEnvironment(environment)) {
|
||||
throw new Error("Invalid environment. Use one of 'production', 'preview', or 'development'.");
|
||||
}
|
||||
|
||||
const environments = flags.environment
|
||||
? flags.environment
|
||||
: environment
|
||||
? [environment as EnvironmentVariableEnvironment]
|
||||
: undefined;
|
||||
|
||||
if (flags['non-interactive']) {
|
||||
if (!flags['variable-name']) {
|
||||
throw new Error(
|
||||
`Environment variable needs 'name' to be specified when running in non-interactive mode. Run the command with ${chalk.bold(
|
||||
'--variable-name VARIABLE_NAME'
|
||||
)} flag to fix the issue`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...flags,
|
||||
environment: environments,
|
||||
};
|
||||
}
|
||||
}
|
||||
-192
@@ -1,192 +0,0 @@
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import { EASMultiEnvironmentFlag, EASNonInteractiveFlag } from '../../commandUtils/flags';
|
||||
import { EnvironmentVariableEnvironment } 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';
|
||||
import { formatVariableName, isEnvironment } from '../../utils/variableUtils';
|
||||
|
||||
type UnlinkFlags = {
|
||||
'variable-name'?: string;
|
||||
'non-interactive': boolean;
|
||||
environment?: EnvironmentVariableEnvironment[];
|
||||
};
|
||||
|
||||
export default class EnvUnlink extends EasCommand {
|
||||
static override description =
|
||||
'unlink an account-wide environment variable from the current project';
|
||||
|
||||
// for now we only roll out global account-wide env variables so this should stay hidden
|
||||
static override hidden = true;
|
||||
|
||||
static override flags = {
|
||||
'variable-name': Flags.string({
|
||||
description: 'Name of the variable',
|
||||
}),
|
||||
...EASMultiEnvironmentFlag,
|
||||
...EASNonInteractiveFlag,
|
||||
};
|
||||
|
||||
static override contextDefinition = {
|
||||
...this.ContextOptions.ProjectId,
|
||||
...this.ContextOptions.LoggedIn,
|
||||
};
|
||||
|
||||
static override args = [
|
||||
{
|
||||
name: 'environment',
|
||||
description:
|
||||
"Environment to unlink the variable from. One of 'production', 'preview', or 'development'.",
|
||||
required: false,
|
||||
},
|
||||
];
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { args, flags } = await this.parse(EnvUnlink);
|
||||
|
||||
let {
|
||||
'variable-name': name,
|
||||
'non-interactive': nonInteractive,
|
||||
environment: unlinkEnvironments,
|
||||
} = this.validateInputs(flags, args);
|
||||
|
||||
const {
|
||||
projectId,
|
||||
loggedIn: { graphqlClient },
|
||||
} = await this.getContextAsync(EnvUnlink, {
|
||||
nonInteractive,
|
||||
});
|
||||
|
||||
const projectDisplayName = await getDisplayNameForProjectIdAsync(graphqlClient, projectId);
|
||||
const variables = await EnvironmentVariablesQuery.sharedAsync(graphqlClient, {
|
||||
appId: projectId,
|
||||
filterNames: name ? [name] : undefined,
|
||||
});
|
||||
|
||||
let selectedVariable = variables[0];
|
||||
|
||||
if (variables.length > 1) {
|
||||
if (nonInteractive) {
|
||||
throw new Error("Multiple variables found, please select one using '--variable-name'");
|
||||
}
|
||||
selectedVariable = await selectAsync(
|
||||
'Select account-wide variable',
|
||||
variables.map(variable => ({
|
||||
title: formatVariableName(variable),
|
||||
value: variable,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
if (!selectedVariable) {
|
||||
throw new Error(`Account-wide variable ${name} doesn't exist`);
|
||||
}
|
||||
|
||||
let explicitSelect = false;
|
||||
|
||||
if (!nonInteractive && !unlinkEnvironments) {
|
||||
const selectedEnvironments =
|
||||
(selectedVariable.linkedEnvironments ?? []).length > 0
|
||||
? selectedVariable.linkedEnvironments
|
||||
: selectedVariable.environments;
|
||||
const environments = await promptVariableEnvironmentAsync({
|
||||
nonInteractive,
|
||||
multiple: true,
|
||||
selectedEnvironments: selectedEnvironments ?? [],
|
||||
});
|
||||
explicitSelect = true;
|
||||
unlinkEnvironments = Object.values(EnvironmentVariableEnvironment).filter(
|
||||
env => !environments.includes(env)
|
||||
);
|
||||
}
|
||||
|
||||
if (!unlinkEnvironments) {
|
||||
await EnvironmentVariableMutation.unlinkSharedEnvironmentVariableAsync(
|
||||
graphqlClient,
|
||||
selectedVariable.id,
|
||||
projectId
|
||||
);
|
||||
Log.withTick(
|
||||
`Unlinked variable ${chalk.bold(selectedVariable.name)} from project ${chalk.bold(
|
||||
projectDisplayName
|
||||
)} in ${selectedVariable.environments?.join(', ').toLocaleLowerCase()}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const environment of Object.values(EnvironmentVariableEnvironment)) {
|
||||
if (
|
||||
selectedVariable.linkedEnvironments?.includes(environment) !==
|
||||
unlinkEnvironments.includes(environment)
|
||||
) {
|
||||
if (!explicitSelect && unlinkEnvironments.includes(environment)) {
|
||||
Log.withTick(
|
||||
`Variable ${chalk.bold(
|
||||
selectedVariable.name
|
||||
)} is already unlinked from ${environment.toLocaleLowerCase()}.`
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (unlinkEnvironments.includes(environment)) {
|
||||
await EnvironmentVariableMutation.unlinkSharedEnvironmentVariableAsync(
|
||||
graphqlClient,
|
||||
selectedVariable.id,
|
||||
projectId,
|
||||
environment
|
||||
);
|
||||
Log.withTick(
|
||||
`Unlinked variable ${chalk.bold(selectedVariable.name)} from project ${chalk.bold(
|
||||
projectDisplayName
|
||||
)} in ${environment.toLocaleLowerCase()}.`
|
||||
);
|
||||
} else if (explicitSelect) {
|
||||
await EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync(
|
||||
graphqlClient,
|
||||
selectedVariable.id,
|
||||
projectId,
|
||||
environment
|
||||
);
|
||||
Log.withTick(
|
||||
`Linked variable ${chalk.bold(selectedVariable.name)} to project ${chalk.bold(
|
||||
projectDisplayName
|
||||
)} in ${environment.toLocaleLowerCase()}.`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private validateInputs(
|
||||
flags: UnlinkFlags,
|
||||
{ environment }: { environment?: string }
|
||||
): UnlinkFlags {
|
||||
if (flags['non-interactive']) {
|
||||
if (!flags['variable-name']) {
|
||||
throw new Error(
|
||||
'Current name is required in non-interactive mode. Run the command with --variable-name flag.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (environment) {
|
||||
environment = environment.toUpperCase();
|
||||
if (!isEnvironment(environment)) {
|
||||
throw new Error(
|
||||
"Invalid environment. Use one of 'production', 'preview', or 'development'."
|
||||
);
|
||||
}
|
||||
return {
|
||||
environment: [environment],
|
||||
...flags,
|
||||
};
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
@@ -1,50 +1,13 @@
|
||||
import chalk from 'chalk';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
|
||||
import { EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
|
||||
import { withErrorHandlingAsync } from '../../graphql/client';
|
||||
import {
|
||||
BackgroundJobReceiptDataFragment,
|
||||
ScheduleUpdateGroupDeletionMutation,
|
||||
ScheduleUpdateGroupDeletionMutationVariables,
|
||||
} from '../../graphql/generated';
|
||||
import { BackgroundJobReceiptNode } from '../../graphql/types/BackgroundJobReceipt';
|
||||
import Log from '../../log';
|
||||
import { confirmAsync } from '../../prompts';
|
||||
import { scheduleUpdateGroupDeletionAsync } from '../../update/delete';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
import { pollForBackgroundJobReceiptAsync } from '../../utils/pollForBackgroundJobReceiptAsync';
|
||||
|
||||
async function scheduleUpdateGroupDeletionAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
{
|
||||
group,
|
||||
}: {
|
||||
group: string;
|
||||
}
|
||||
): Promise<BackgroundJobReceiptDataFragment> {
|
||||
const result = await withErrorHandlingAsync(
|
||||
graphqlClient
|
||||
.mutation<ScheduleUpdateGroupDeletionMutation, ScheduleUpdateGroupDeletionMutationVariables>(
|
||||
gql`
|
||||
mutation ScheduleUpdateGroupDeletion($group: ID!) {
|
||||
update {
|
||||
scheduleUpdateGroupDeletion(group: $group) {
|
||||
id
|
||||
...BackgroundJobReceiptData
|
||||
}
|
||||
}
|
||||
}
|
||||
${BackgroundJobReceiptNode}
|
||||
`,
|
||||
{ group }
|
||||
)
|
||||
.toPromise()
|
||||
);
|
||||
return result.update.scheduleUpdateGroupDeletion;
|
||||
}
|
||||
|
||||
export default class UpdateDelete extends EasCommand {
|
||||
static override description = 'delete all the updates in an update group';
|
||||
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
import { Platform } from '@expo/config';
|
||||
import { Flags } from '@oclif/core';
|
||||
|
||||
import { selectBranchOnAppAsync } from '../../branch/queries';
|
||||
import { selectChannelOnAppAsync } from '../../channel/queries';
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
|
||||
import { EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
|
||||
import { getPaginatedQueryOptions } from '../../commandUtils/pagination';
|
||||
import { BranchQuery } from '../../graphql/queries/BranchQuery';
|
||||
import { UpdateQuery } from '../../graphql/queries/UpdateQuery';
|
||||
import Log from '../../log';
|
||||
import { promptAsync } from '../../prompts';
|
||||
import { getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync } from '../../update/getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync';
|
||||
import { selectUpdateGroupOnBranchAsync } from '../../update/queries';
|
||||
import { UpdateToRepublish, republishAsync } from '../../update/republish';
|
||||
import { truncateString as truncateUpdateMessage } from '../../update/utils';
|
||||
import {
|
||||
UpdateToRepublish,
|
||||
getOrAskUpdateMessageAsync,
|
||||
getUpdateGroupOrAskForUpdateGroupAsync,
|
||||
republishAsync,
|
||||
} from '../../update/republish';
|
||||
import { getCodeSigningInfoAsync } from '../../utils/code-signing';
|
||||
import { enableJsonOutput } from '../../utils/json';
|
||||
|
||||
@@ -120,7 +118,11 @@ export default class UpdateRepublish extends EasCommand {
|
||||
|
||||
const codeSigningInfo = await getCodeSigningInfoAsync(exp, flags.privateKeyPath);
|
||||
|
||||
const existingUpdates = await getOrAskUpdatesAsync(graphqlClient, projectId, flags);
|
||||
const existingUpdates = await getUpdateGroupOrAskForUpdateGroupAsync(
|
||||
graphqlClient,
|
||||
projectId,
|
||||
flags
|
||||
);
|
||||
const updatesToPublish = existingUpdates.filter(update =>
|
||||
flags.platform.includes(update.platform as Platform)
|
||||
);
|
||||
@@ -234,177 +236,3 @@ async function getOrAskTargetBranchAsync(
|
||||
// if neither provided, assume republish on same branch
|
||||
return { branchId: arbitraryUpdate.branchId, branchName: arbitraryUpdate.branchName };
|
||||
}
|
||||
|
||||
/** Retrieve the update group from either the update group id, or select from branch name. */
|
||||
async function getOrAskUpdatesAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
projectId: string,
|
||||
flags: UpdateRepublishFlags
|
||||
): Promise<UpdateToRepublish[]> {
|
||||
if (flags.groupId) {
|
||||
const updateGroup = await UpdateQuery.viewUpdateGroupAsync(graphqlClient, {
|
||||
groupId: flags.groupId,
|
||||
});
|
||||
|
||||
return updateGroup.map(update => ({
|
||||
...update,
|
||||
groupId: update.group,
|
||||
branchId: update.branch.id,
|
||||
branchName: update.branch.name,
|
||||
}));
|
||||
}
|
||||
|
||||
if (flags.nonInteractive) {
|
||||
throw new Error('Must supply --group when in non-interactive mode');
|
||||
}
|
||||
|
||||
if (flags.branchName) {
|
||||
return await askUpdatesFromBranchNameAsync(graphqlClient, {
|
||||
...flags,
|
||||
branchName: flags.branchName,
|
||||
projectId,
|
||||
});
|
||||
}
|
||||
|
||||
if (flags.channelName) {
|
||||
return await askUpdatesFromChannelNameAsync(graphqlClient, {
|
||||
...flags,
|
||||
channelName: flags.channelName,
|
||||
projectId,
|
||||
});
|
||||
}
|
||||
|
||||
const { choice } = await promptAsync({
|
||||
type: 'select',
|
||||
message: 'Find update by branch or channel?',
|
||||
name: 'choice',
|
||||
choices: [
|
||||
{ title: 'Branch', value: 'branch' },
|
||||
{ title: 'Channel', value: 'channel' },
|
||||
],
|
||||
});
|
||||
|
||||
if (choice === 'channel') {
|
||||
const { name } = await selectChannelOnAppAsync(graphqlClient, {
|
||||
projectId,
|
||||
selectionPromptTitle: 'Select a channel to view',
|
||||
paginatedQueryOptions: {
|
||||
json: flags.json,
|
||||
nonInteractive: flags.nonInteractive,
|
||||
offset: 0,
|
||||
},
|
||||
});
|
||||
|
||||
return await askUpdatesFromChannelNameAsync(graphqlClient, {
|
||||
...flags,
|
||||
channelName: name,
|
||||
projectId,
|
||||
});
|
||||
} else if (choice === 'branch') {
|
||||
const { name } = await selectBranchOnAppAsync(graphqlClient, {
|
||||
projectId,
|
||||
promptTitle: 'Select branch from which to choose update',
|
||||
displayTextForListItem: updateBranch => ({
|
||||
title: updateBranch.name,
|
||||
}),
|
||||
// discard limit and offset because this query is not their intended target
|
||||
paginatedQueryOptions: {
|
||||
json: flags.json,
|
||||
nonInteractive: flags.nonInteractive,
|
||||
offset: 0,
|
||||
},
|
||||
});
|
||||
|
||||
return await askUpdatesFromBranchNameAsync(graphqlClient, {
|
||||
...flags,
|
||||
branchName: name,
|
||||
projectId,
|
||||
});
|
||||
} else {
|
||||
throw new Error('Must choose update via channel or branch');
|
||||
}
|
||||
}
|
||||
|
||||
/** Ask the user which update needs to be republished by branch name, this requires interactive mode */
|
||||
async function askUpdatesFromBranchNameAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
{
|
||||
projectId,
|
||||
branchName,
|
||||
json,
|
||||
nonInteractive,
|
||||
}: { projectId: string; branchName: string; json: boolean; nonInteractive: boolean }
|
||||
): Promise<UpdateToRepublish[]> {
|
||||
const updateGroup = await selectUpdateGroupOnBranchAsync(graphqlClient, {
|
||||
projectId,
|
||||
branchName,
|
||||
paginatedQueryOptions: getPaginatedQueryOptions({ json, 'non-interactive': nonInteractive }),
|
||||
});
|
||||
|
||||
return updateGroup.map(update => ({
|
||||
...update,
|
||||
groupId: update.group,
|
||||
branchId: update.branch.id,
|
||||
branchName: update.branch.name,
|
||||
}));
|
||||
}
|
||||
/** Ask the user which update needs to be republished by channel name, this requires interactive mode */
|
||||
async function askUpdatesFromChannelNameAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
{
|
||||
projectId,
|
||||
channelName,
|
||||
json,
|
||||
nonInteractive,
|
||||
}: { projectId: string; channelName: string; json: boolean; nonInteractive: boolean }
|
||||
): Promise<UpdateToRepublish[]> {
|
||||
const { branchName } = await getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync(
|
||||
graphqlClient,
|
||||
projectId,
|
||||
channelName
|
||||
);
|
||||
|
||||
return await askUpdatesFromBranchNameAsync(graphqlClient, {
|
||||
projectId,
|
||||
branchName,
|
||||
json,
|
||||
nonInteractive,
|
||||
});
|
||||
}
|
||||
|
||||
/** Get or ask the user for the update (group) message for the republish */
|
||||
async function getOrAskUpdateMessageAsync(
|
||||
updates: UpdateToRepublish[],
|
||||
flags: UpdateRepublishFlags
|
||||
): Promise<string> {
|
||||
if (flags.updateMessage) {
|
||||
return sanitizeUpdateMessage(flags.updateMessage);
|
||||
}
|
||||
|
||||
if (flags.nonInteractive || flags.json) {
|
||||
throw new Error('Must supply --message when in non-interactive mode');
|
||||
}
|
||||
|
||||
// This command only uses a single update group to republish, meaning these values are always identical
|
||||
const oldGroupId = updates[0].groupId;
|
||||
const oldUpdateMessage = updates[0].message;
|
||||
|
||||
const { updateMessage } = await promptAsync({
|
||||
type: 'text',
|
||||
name: 'updateMessage',
|
||||
message: 'Provide an update message.',
|
||||
initial: `Republish "${oldUpdateMessage!}" - group: ${oldGroupId}`,
|
||||
validate: (value: any) => (value ? true : 'Update message may not be empty.'),
|
||||
});
|
||||
|
||||
return sanitizeUpdateMessage(updateMessage);
|
||||
}
|
||||
|
||||
function sanitizeUpdateMessage(updateMessage: string): string {
|
||||
if (updateMessage !== truncateUpdateMessage(updateMessage, 1024)) {
|
||||
Log.warn('Update message exceeds the allowed 1024 character limit, truncated update message.');
|
||||
return truncateUpdateMessage(updateMessage, 1024);
|
||||
}
|
||||
|
||||
return updateMessage;
|
||||
}
|
||||
@@ -0,0 +1,416 @@
|
||||
import { ExpoConfig } from '@expo/config';
|
||||
import { Flags } from '@oclif/core';
|
||||
import assert from 'assert';
|
||||
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
|
||||
import { EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
|
||||
import Log, { learnMore } from '../../log';
|
||||
import { enforceRollBackToEmbeddedUpdateSupportAsync } from '../../project/projectUtils';
|
||||
import { UpdatePublishPlatform, getUpdateMessageForCommandAsync } from '../../project/publish';
|
||||
import { confirmAsync, promptAsync } from '../../prompts';
|
||||
import { scheduleUpdateGroupDeletionAsync } from '../../update/delete';
|
||||
import {
|
||||
UpdateToRepublish,
|
||||
askUpdateGroupForEachPublishPlatformFilteringByRuntimeVersionAsync,
|
||||
getOrAskUpdateMessageAsync,
|
||||
getUpdateGroupAsync,
|
||||
republishAsync,
|
||||
} from '../../update/republish';
|
||||
import { publishRollBackToEmbeddedUpdateAsync } from '../../update/roll-back-to-embedded';
|
||||
import { CodeSigningInfo, getCodeSigningInfoAsync } from '../../utils/code-signing';
|
||||
import { enableJsonOutput } from '../../utils/json';
|
||||
import { pollForBackgroundJobReceiptAsync } from '../../utils/pollForBackgroundJobReceiptAsync';
|
||||
import { Client } from '../../vcs/vcs';
|
||||
|
||||
type RolloutUpdate = UpdateToRepublish & {
|
||||
rolloutPercentage: NonNullable<UpdateToRepublish['rolloutPercentage']>;
|
||||
};
|
||||
|
||||
type RolloutUpdateWithControlUpdate = RolloutUpdate & {
|
||||
rolloutControlUpdate: NonNullable<UpdateToRepublish['rolloutControlUpdate']>;
|
||||
};
|
||||
|
||||
type UpdateRevertUpdateRolloutRawFlags = {
|
||||
branch?: string;
|
||||
channel?: string;
|
||||
group?: string;
|
||||
message?: string;
|
||||
'private-key-path'?: string;
|
||||
'non-interactive': boolean;
|
||||
json?: boolean;
|
||||
};
|
||||
|
||||
type UpdateRevertUpdateRolloutFlags = {
|
||||
branchName?: string;
|
||||
channelName?: string;
|
||||
groupId?: string;
|
||||
updateMessage?: string;
|
||||
privateKeyPath?: string;
|
||||
nonInteractive: boolean;
|
||||
json: boolean;
|
||||
};
|
||||
|
||||
export function nonNullish<TValue>(value: TValue | null | undefined): value is NonNullable<TValue> {
|
||||
return value !== null && value !== undefined;
|
||||
}
|
||||
|
||||
export default class UpdateRevertUpdateRollout extends EasCommand {
|
||||
static override description = 'revert a rollout update for a project';
|
||||
|
||||
static override flags = {
|
||||
channel: Flags.string({
|
||||
description: 'Channel name to select an update group to revert the rollout update from',
|
||||
exclusive: ['branch', 'group'],
|
||||
}),
|
||||
branch: Flags.string({
|
||||
description: 'Branch name to select an update group to revert the rollout update from',
|
||||
exclusive: ['channel', 'group'],
|
||||
}),
|
||||
group: Flags.string({
|
||||
description: 'Rollout update group ID to revert',
|
||||
exclusive: ['branch', 'channel'],
|
||||
}),
|
||||
message: Flags.string({
|
||||
char: 'm',
|
||||
description: 'Short message describing the revert',
|
||||
required: false,
|
||||
}),
|
||||
'private-key-path': Flags.string({
|
||||
description: `File containing the PEM-encoded private key corresponding to the certificate in expo-updates' configuration. Defaults to a file named "private-key.pem" in the certificate's directory. Only relevant if you are using code signing: https://docs.expo.dev/eas-update/code-signing/`,
|
||||
required: false,
|
||||
}),
|
||||
...EasNonInteractiveAndJsonFlags,
|
||||
};
|
||||
|
||||
static override contextDefinition = {
|
||||
...this.ContextOptions.ProjectConfig,
|
||||
...this.ContextOptions.LoggedIn,
|
||||
...this.ContextOptions.Vcs,
|
||||
};
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { flags: rawFlags } = await this.parse(UpdateRevertUpdateRollout);
|
||||
const flags = this.sanitizeFlags(rawFlags);
|
||||
|
||||
const {
|
||||
privateProjectConfig: { exp, projectId, projectDir },
|
||||
loggedIn: { graphqlClient },
|
||||
vcsClient,
|
||||
} = await this.getContextAsync(UpdateRevertUpdateRollout, {
|
||||
nonInteractive: flags.nonInteractive,
|
||||
withServerSideEnvironment: null,
|
||||
});
|
||||
|
||||
if (flags.json) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
|
||||
const codeSigningInfo = await getCodeSigningInfoAsync(exp, flags.privateKeyPath);
|
||||
|
||||
let updateGroupToRepublish: RolloutUpdate[];
|
||||
if (flags.groupId) {
|
||||
const updateGroup = await getUpdateGroupAsync(graphqlClient, flags.groupId);
|
||||
if (!updateGroupIsRolloutUpdateGroup(updateGroup)) {
|
||||
throw new Error(
|
||||
`The update group with ID "${flags.groupId}" is not a rollout update group.`
|
||||
);
|
||||
}
|
||||
updateGroupToRepublish = updateGroup;
|
||||
} else {
|
||||
const latestUpdateGroupForEachPublishPlatform =
|
||||
await askUpdateGroupForEachPublishPlatformFilteringByRuntimeVersionAsync(
|
||||
graphqlClient,
|
||||
projectId,
|
||||
flags
|
||||
);
|
||||
|
||||
const uniqueUpdateGroups = getUniqueUpdateGroups(
|
||||
Object.values(latestUpdateGroupForEachPublishPlatform).filter(nonNullish)
|
||||
);
|
||||
|
||||
const rolloutUpdateGroups = uniqueUpdateGroups.filter(updateGroupIsRolloutUpdateGroup);
|
||||
|
||||
if (rolloutUpdateGroups.length === 0) {
|
||||
throw new Error(`No rollout update groups found.`);
|
||||
}
|
||||
|
||||
if (rolloutUpdateGroups.length === 1) {
|
||||
updateGroupToRepublish = rolloutUpdateGroups[0];
|
||||
} else {
|
||||
const { choice: chosenId } = await promptAsync({
|
||||
type: 'select',
|
||||
message: 'Which rollout update group would you like to revert?',
|
||||
name: 'choice',
|
||||
choices: rolloutUpdateGroups.map(ug => ({
|
||||
title: `Rollout update group ID: ${ug[0].groupId}, Platform: ${ug[0].platform}, Rollout Percentage: ${ug[0].rolloutPercentage}`,
|
||||
value: ug[0].groupId,
|
||||
})),
|
||||
});
|
||||
|
||||
if (!chosenId) {
|
||||
throw new Error('No rollout update group selected.');
|
||||
}
|
||||
|
||||
const chosenUpdateGroup = rolloutUpdateGroups.find(ug => ug[0].groupId === chosenId);
|
||||
|
||||
if (!chosenUpdateGroup) {
|
||||
throw new Error('No rollout update group selected.');
|
||||
}
|
||||
|
||||
updateGroupToRepublish = chosenUpdateGroup;
|
||||
}
|
||||
}
|
||||
|
||||
const rolloutUpdateGroupWithControlUpdates: RolloutUpdateWithControlUpdate[] | null =
|
||||
updateGroupIsUpdateGroupWithControlUpdate(updateGroupToRepublish)
|
||||
? updateGroupToRepublish
|
||||
: null;
|
||||
if (rolloutUpdateGroupWithControlUpdates) {
|
||||
await this.deleteRolloutUpdateGroupAndRepublishControlUpdatesAsync({
|
||||
graphqlClient,
|
||||
exp,
|
||||
projectId,
|
||||
rolloutUpdateGroupWithControlUpdates,
|
||||
codeSigningInfo,
|
||||
flags,
|
||||
});
|
||||
} else {
|
||||
await this.deleteRolloutUpdateGroupAndPublishRollBackToEmbeddedAsync({
|
||||
graphqlClient,
|
||||
vcsClient,
|
||||
exp,
|
||||
projectDir,
|
||||
projectId,
|
||||
rolloutUpdateGroup: updateGroupToRepublish,
|
||||
codeSigningInfo,
|
||||
flags,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async deleteRolloutUpdateGroupAndRepublishControlUpdatesAsync({
|
||||
graphqlClient,
|
||||
exp,
|
||||
projectId,
|
||||
rolloutUpdateGroupWithControlUpdates,
|
||||
codeSigningInfo,
|
||||
flags,
|
||||
}: {
|
||||
graphqlClient: ExpoGraphqlClient;
|
||||
exp: ExpoConfig;
|
||||
projectId: string;
|
||||
rolloutUpdateGroupWithControlUpdates: RolloutUpdateWithControlUpdate[];
|
||||
codeSigningInfo: CodeSigningInfo | undefined;
|
||||
flags: UpdateRevertUpdateRolloutFlags;
|
||||
}): Promise<void> {
|
||||
const controlUpdateGroupIdsToRepublish = Array.from(
|
||||
new Set(rolloutUpdateGroupWithControlUpdates.map(update => update.rolloutControlUpdate.group))
|
||||
);
|
||||
|
||||
const updateGroupsToRepublish = await Promise.all(
|
||||
controlUpdateGroupIdsToRepublish.map(controlUpdateGroupIdToRepublish =>
|
||||
getUpdateGroupAsync(graphqlClient, controlUpdateGroupIdToRepublish)
|
||||
)
|
||||
);
|
||||
|
||||
const updateGroupOrGroupsClause =
|
||||
controlUpdateGroupIdsToRepublish.length > 1
|
||||
? `control update groups (IDs: ${controlUpdateGroupIdsToRepublish
|
||||
.map(id => `"${id}"`)
|
||||
.join(', ')})`
|
||||
: `control update group (ID: "${controlUpdateGroupIdsToRepublish[0]}")`;
|
||||
|
||||
if (!flags.nonInteractive) {
|
||||
const confirmMessage = `Are you sure you want to revert the rollout update group with ID "${rolloutUpdateGroupWithControlUpdates[0].groupId}"? This will delete the rollout update group and republish the ${updateGroupOrGroupsClause}.`;
|
||||
const didConfirm = await confirmAsync({ message: confirmMessage });
|
||||
if (!didConfirm) {
|
||||
throw new Error('Aborting...');
|
||||
}
|
||||
}
|
||||
|
||||
const updateMessages: string[] = [];
|
||||
for (const updateGroup of updateGroupsToRepublish) {
|
||||
updateMessages.push(await getOrAskUpdateMessageAsync(updateGroup, flags));
|
||||
}
|
||||
|
||||
// assert all updateGroupsToRepublish have the same branch name and id
|
||||
const branchNames = updateGroupsToRepublish.flatMap(updateGroup => updateGroup[0].branchName);
|
||||
const branchIds = updateGroupsToRepublish.map(updateGroup => updateGroup[0].branchId);
|
||||
assert(
|
||||
branchNames.every(name => name === branchNames[0]),
|
||||
'All update groups being republished must belong to the same branch.'
|
||||
);
|
||||
assert(
|
||||
branchIds.every(id => id === branchIds[0]),
|
||||
'All update groups being republished must belong to the same branch.'
|
||||
);
|
||||
const targetBranch = {
|
||||
branchName: branchNames[0],
|
||||
branchId: branchIds[0],
|
||||
};
|
||||
|
||||
await this.deleteRolloutUpdateGroupAsync({
|
||||
graphqlClient,
|
||||
rolloutUpdateGroup: rolloutUpdateGroupWithControlUpdates,
|
||||
});
|
||||
|
||||
for (let i = 0; i < updateGroupsToRepublish.length; i++) {
|
||||
const updateGroupToRepublish = updateGroupsToRepublish[i];
|
||||
const updateMessage = updateMessages[i];
|
||||
|
||||
await republishAsync({
|
||||
graphqlClient,
|
||||
app: { exp, projectId },
|
||||
updatesToPublish: updateGroupToRepublish,
|
||||
targetBranch,
|
||||
updateMessage,
|
||||
codeSigningInfo,
|
||||
json: flags.json,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async deleteRolloutUpdateGroupAndPublishRollBackToEmbeddedAsync({
|
||||
graphqlClient,
|
||||
vcsClient,
|
||||
exp,
|
||||
projectDir,
|
||||
projectId,
|
||||
rolloutUpdateGroup,
|
||||
codeSigningInfo,
|
||||
flags,
|
||||
}: {
|
||||
graphqlClient: ExpoGraphqlClient;
|
||||
vcsClient: Client;
|
||||
exp: ExpoConfig;
|
||||
projectDir: string;
|
||||
projectId: string;
|
||||
rolloutUpdateGroup: RolloutUpdate[];
|
||||
codeSigningInfo: CodeSigningInfo | undefined;
|
||||
flags: UpdateRevertUpdateRolloutFlags;
|
||||
}): Promise<void> {
|
||||
const rolloutUpdateGroupId = rolloutUpdateGroup[0].groupId;
|
||||
|
||||
if (!flags.nonInteractive) {
|
||||
const confirmMessage = `Are you sure you want to revert the rollout update group with ID "${rolloutUpdateGroupId}"? This will delete the rollout update group and publish a new roll-back-to-embedded update (no control update to roll back to), whose behavior may not be a true revert depending on the previous state of the branch. ${learnMore(
|
||||
'https://expo.fyi/eas-update-update-rollouts',
|
||||
{ learnMoreMessage: 'More info' }
|
||||
)})`;
|
||||
const didConfirm = await confirmAsync({ message: confirmMessage });
|
||||
if (!didConfirm) {
|
||||
throw new Error('Aborting...');
|
||||
}
|
||||
}
|
||||
|
||||
// check that the expo-updates package version supports roll back to embedded
|
||||
await enforceRollBackToEmbeddedUpdateSupportAsync(projectDir);
|
||||
const updateMessage = await getUpdateMessageForCommandAsync(vcsClient, {
|
||||
updateMessageArg: flags.updateMessage,
|
||||
autoFlag: false,
|
||||
nonInteractive: flags.nonInteractive,
|
||||
jsonFlag: flags.json,
|
||||
});
|
||||
|
||||
await this.deleteRolloutUpdateGroupAsync({
|
||||
graphqlClient,
|
||||
rolloutUpdateGroup,
|
||||
});
|
||||
|
||||
const platforms = rolloutUpdateGroup.map(update => update.platform) as UpdatePublishPlatform[];
|
||||
const runtimeVersion = rolloutUpdateGroup[0].runtimeVersion;
|
||||
const targetBranch = {
|
||||
name: rolloutUpdateGroup[0].branchName,
|
||||
id: rolloutUpdateGroup[0].branchId,
|
||||
};
|
||||
|
||||
await publishRollBackToEmbeddedUpdateAsync({
|
||||
graphqlClient,
|
||||
projectId,
|
||||
exp,
|
||||
updateMessage,
|
||||
branch: targetBranch,
|
||||
codeSigningInfo,
|
||||
platforms,
|
||||
runtimeVersion,
|
||||
json: flags.json,
|
||||
});
|
||||
}
|
||||
|
||||
private async deleteRolloutUpdateGroupAsync({
|
||||
graphqlClient,
|
||||
rolloutUpdateGroup,
|
||||
}: {
|
||||
graphqlClient: ExpoGraphqlClient;
|
||||
rolloutUpdateGroup: RolloutUpdate[];
|
||||
}): Promise<void> {
|
||||
const rolloutUpdateGroupId = rolloutUpdateGroup[0].groupId;
|
||||
|
||||
const updateGroupDeletionReceipt = await scheduleUpdateGroupDeletionAsync(graphqlClient, {
|
||||
group: rolloutUpdateGroupId,
|
||||
});
|
||||
const successfulReceipt = await pollForBackgroundJobReceiptAsync(
|
||||
graphqlClient,
|
||||
updateGroupDeletionReceipt
|
||||
);
|
||||
Log.debug('Rollout update group deletion result', { successfulReceipt });
|
||||
}
|
||||
|
||||
private sanitizeFlags(
|
||||
rawFlags: UpdateRevertUpdateRolloutRawFlags
|
||||
): UpdateRevertUpdateRolloutFlags {
|
||||
const branchName = rawFlags.branch;
|
||||
const channelName = rawFlags.channel;
|
||||
const groupId = rawFlags.group;
|
||||
const nonInteractive = rawFlags['non-interactive'];
|
||||
const privateKeyPath = rawFlags['private-key-path'];
|
||||
|
||||
if (nonInteractive && !groupId) {
|
||||
throw new Error('Only --group can be used in non-interactive mode');
|
||||
}
|
||||
|
||||
return {
|
||||
branchName,
|
||||
channelName,
|
||||
groupId,
|
||||
|
||||
updateMessage: rawFlags.message,
|
||||
privateKeyPath,
|
||||
json: rawFlags.json ?? false,
|
||||
nonInteractive,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function getUniqueUpdateGroups(updateGroups: UpdateToRepublish[][]): UpdateToRepublish[][] {
|
||||
const uniqueUpdateGroups = new Map<string, UpdateToRepublish[]>();
|
||||
for (const updateGroup of updateGroups) {
|
||||
const groupId = updateGroup[0].groupId;
|
||||
if (!uniqueUpdateGroups.has(groupId)) {
|
||||
uniqueUpdateGroups.set(groupId, updateGroup);
|
||||
}
|
||||
}
|
||||
return Array.from(uniqueUpdateGroups.values());
|
||||
}
|
||||
|
||||
function updateGroupIsRolloutUpdateGroup(
|
||||
updateGroup: UpdateToRepublish[]
|
||||
): updateGroup is RolloutUpdate[] {
|
||||
return updateGroup.every(updateIsRolloutUpdate);
|
||||
}
|
||||
|
||||
function updateIsRolloutUpdate(updateGroup: UpdateToRepublish): updateGroup is RolloutUpdate {
|
||||
return updateGroup.rolloutPercentage !== undefined && updateGroup.rolloutPercentage !== null;
|
||||
}
|
||||
|
||||
function updateGroupIsUpdateGroupWithControlUpdate(
|
||||
updateGroup: RolloutUpdate[]
|
||||
): updateGroup is RolloutUpdateWithControlUpdate[] {
|
||||
return updateGroup.every(updateIsRolloutWithControlUpdate);
|
||||
}
|
||||
|
||||
function updateIsRolloutWithControlUpdate(
|
||||
updateGroup: RolloutUpdate
|
||||
): updateGroup is RolloutUpdateWithControlUpdate {
|
||||
return !!updateGroup.rolloutControlUpdate;
|
||||
}
|
||||
@@ -1,51 +1,24 @@
|
||||
import { Platform as PublishPlatform } from '@expo/config';
|
||||
import { EasJson, EasJsonAccessor, EasJsonUtils } from '@expo/eas-json';
|
||||
import { Errors, Flags } from '@oclif/core';
|
||||
import nullthrows from 'nullthrows';
|
||||
|
||||
import { ensureBranchExistsAsync } from '../../branch/queries';
|
||||
import { getUpdateGroupUrl } from '../../build/utils/url';
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
|
||||
import { EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
|
||||
import { getPaginatedQueryOptions } from '../../commandUtils/pagination';
|
||||
import fetch from '../../fetch';
|
||||
import {
|
||||
PublishUpdateGroupInput,
|
||||
RuntimeFragment,
|
||||
StatuspageServiceName,
|
||||
UpdatePublishMutation,
|
||||
} from '../../graphql/generated';
|
||||
import { PublishMutation } from '../../graphql/mutations/PublishMutation';
|
||||
import { RuntimeQuery } from '../../graphql/queries/RuntimeQuery';
|
||||
import Log, { link } from '../../log';
|
||||
import { ora } from '../../ora';
|
||||
import { StatuspageServiceName } from '../../graphql/generated';
|
||||
import { RequestedPlatform } from '../../platform';
|
||||
import { enforceRollBackToEmbeddedUpdateSupportAsync } from '../../project/projectUtils';
|
||||
import {
|
||||
enforceRollBackToEmbeddedUpdateSupportAsync,
|
||||
getOwnerAccountForProjectIdAsync,
|
||||
} from '../../project/projectUtils';
|
||||
import {
|
||||
RuntimeVersionInfo,
|
||||
UpdatePublishPlatform,
|
||||
defaultPublishPlatforms,
|
||||
getBranchNameForCommandAsync,
|
||||
getRuntimeToPlatformsAndFingerprintInfoMappingFromRuntimeVersionInfoObjects,
|
||||
getUpdateMessageForCommandAsync,
|
||||
} from '../../project/publish';
|
||||
import { ensureEASUpdateIsConfiguredAsync } from '../../update/configure';
|
||||
import { getUpdateJsonInfosForUpdates } from '../../update/utils';
|
||||
import {
|
||||
CodeSigningInfo,
|
||||
checkDirectiveBodyAgainstUpdateInfoGroup,
|
||||
getCodeSigningInfoAsync,
|
||||
getDirectiveBodyAsync,
|
||||
signBody,
|
||||
} from '../../utils/code-signing';
|
||||
import uniqBy from '../../utils/expodash/uniqBy';
|
||||
import formatFields from '../../utils/formatFields';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
import { Connection, QueryParams, selectPaginatedAsync } from '../../utils/relay';
|
||||
import { selectRuntimeOnBranchAsync } from '../../update/queries';
|
||||
import { publishRollBackToEmbeddedUpdateAsync } from '../../update/roll-back-to-embedded';
|
||||
import { getCodeSigningInfoAsync } from '../../utils/code-signing';
|
||||
import { enableJsonOutput } from '../../utils/json';
|
||||
import { maybeWarnAboutEasOutagesAsync } from '../../utils/statuspageService';
|
||||
|
||||
type RawUpdateFlags = {
|
||||
@@ -199,7 +172,7 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
|
||||
const selectedRuntime =
|
||||
runtimeVersionArg ??
|
||||
(
|
||||
await UpdateRollBackToEmbedded.selectRuntimeAsync(graphqlClient, {
|
||||
await selectRuntimeOnBranchAsync(graphqlClient, {
|
||||
appId: projectId,
|
||||
branchName,
|
||||
})
|
||||
@@ -208,196 +181,16 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
|
||||
Errors.error('Must select a runtime or provide the --runtimeVersion flag', { exit: 1 });
|
||||
}
|
||||
|
||||
const runtimeToPlatformsAndFingerprintInfoMapping =
|
||||
getRuntimeToPlatformsAndFingerprintInfoMappingFromRuntimeVersionInfoObjects(
|
||||
realizedPlatforms.map(platform => ({
|
||||
platform,
|
||||
runtimeVersionInfo: {
|
||||
runtimeVersion: selectedRuntime,
|
||||
expoUpdatesRuntimeFingerprint: null,
|
||||
expoUpdatesRuntimeFingerprintHash: null,
|
||||
},
|
||||
}))
|
||||
);
|
||||
|
||||
let newUpdates: UpdatePublishMutation['updateBranch']['publishUpdateGroups'];
|
||||
const publishSpinner = ora('Publishing...').start();
|
||||
try {
|
||||
newUpdates = await this.publishRollbacksAsync({
|
||||
graphqlClient,
|
||||
updateMessage,
|
||||
branchId: branch.id,
|
||||
codeSigningInfo,
|
||||
runtimeToPlatformsAndFingerprintInfoMapping,
|
||||
realizedPlatforms,
|
||||
});
|
||||
publishSpinner.succeed('Published!');
|
||||
} catch (e) {
|
||||
publishSpinner.fail('Failed to publish updates');
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (jsonFlag) {
|
||||
printJsonOnlyOutput(getUpdateJsonInfosForUpdates(newUpdates));
|
||||
} else {
|
||||
Log.addNewLineIfNone();
|
||||
|
||||
for (const runtime of uniqBy(
|
||||
runtimeToPlatformsAndFingerprintInfoMapping,
|
||||
version => version.runtimeVersion
|
||||
)) {
|
||||
const newUpdatesForRuntimeVersion = newUpdates.filter(
|
||||
update => update.runtimeVersion === runtime.runtimeVersion
|
||||
);
|
||||
if (newUpdatesForRuntimeVersion.length === 0) {
|
||||
throw new Error(
|
||||
`Publish response is missing updates with runtime ${runtime.runtimeVersion}.`
|
||||
);
|
||||
}
|
||||
const platforms = newUpdatesForRuntimeVersion.map(update => update.platform);
|
||||
const newAndroidUpdate = newUpdatesForRuntimeVersion.find(
|
||||
update => update.platform === 'android'
|
||||
);
|
||||
const newIosUpdate = newUpdatesForRuntimeVersion.find(update => update.platform === 'ios');
|
||||
const updateGroupId = newUpdatesForRuntimeVersion[0].group;
|
||||
|
||||
const projectName = exp.slug;
|
||||
const accountName = (await getOwnerAccountForProjectIdAsync(graphqlClient, projectId)).name;
|
||||
const updateGroupUrl = getUpdateGroupUrl(accountName, projectName, updateGroupId);
|
||||
const updateGroupLink = link(updateGroupUrl, { dim: false });
|
||||
|
||||
Log.log(
|
||||
formatFields([
|
||||
{ label: 'Branch', value: branchName },
|
||||
{ label: 'Runtime version', value: runtime.runtimeVersion },
|
||||
{ label: 'Platform', value: platforms.join(', ') },
|
||||
{ label: 'Update group ID', value: updateGroupId },
|
||||
...(newAndroidUpdate
|
||||
? [{ label: 'Android update ID', value: newAndroidUpdate.id }]
|
||||
: []),
|
||||
...(newIosUpdate ? [{ label: 'iOS update ID', value: newIosUpdate.id }] : []),
|
||||
{ label: 'Message', value: updateMessage ?? '' },
|
||||
{ label: 'EAS Dashboard', value: updateGroupLink },
|
||||
])
|
||||
);
|
||||
Log.addNewLineIfNone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async publishRollbacksAsync({
|
||||
graphqlClient,
|
||||
updateMessage,
|
||||
branchId,
|
||||
codeSigningInfo,
|
||||
runtimeToPlatformsAndFingerprintInfoMapping,
|
||||
realizedPlatforms,
|
||||
}: {
|
||||
graphqlClient: ExpoGraphqlClient;
|
||||
updateMessage: string | undefined;
|
||||
branchId: string;
|
||||
codeSigningInfo: CodeSigningInfo | undefined;
|
||||
runtimeToPlatformsAndFingerprintInfoMapping: (RuntimeVersionInfo & {
|
||||
platforms: UpdatePublishPlatform[];
|
||||
})[];
|
||||
realizedPlatforms: PublishPlatform[];
|
||||
}): Promise<UpdatePublishMutation['updateBranch']['publishUpdateGroups']> {
|
||||
const rollbackInfoGroups = Object.fromEntries(
|
||||
realizedPlatforms.map(platform => [platform, true])
|
||||
);
|
||||
|
||||
// Sort the updates into different groups based on their platform specific runtime versions
|
||||
const updateGroups: PublishUpdateGroupInput[] = runtimeToPlatformsAndFingerprintInfoMapping.map(
|
||||
({ runtimeVersion, platforms }) => {
|
||||
const localRollbackInfoGroup = Object.fromEntries(
|
||||
platforms.map(platform => [platform, rollbackInfoGroups[platform]])
|
||||
);
|
||||
|
||||
return {
|
||||
branchId,
|
||||
rollBackToEmbeddedInfoGroup: localRollbackInfoGroup,
|
||||
runtimeVersion,
|
||||
message: updateMessage,
|
||||
awaitingCodeSigningInfo: !!codeSigningInfo,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const newUpdates = await PublishMutation.publishUpdateGroupAsync(graphqlClient, updateGroups);
|
||||
|
||||
if (codeSigningInfo) {
|
||||
Log.log('🔒 Signing roll back');
|
||||
|
||||
const updatesTemp = [...newUpdates];
|
||||
const updateGroupsAndTheirUpdates = updateGroups.map(updateGroup => {
|
||||
const newUpdates = updatesTemp.splice(
|
||||
0,
|
||||
Object.keys(nullthrows(updateGroup.rollBackToEmbeddedInfoGroup)).length
|
||||
);
|
||||
return {
|
||||
updateGroup,
|
||||
newUpdates,
|
||||
};
|
||||
});
|
||||
|
||||
await Promise.all(
|
||||
updateGroupsAndTheirUpdates.map(async ({ newUpdates }) => {
|
||||
await Promise.all(
|
||||
newUpdates.map(async newUpdate => {
|
||||
const response = await fetch(newUpdate.manifestPermalink, {
|
||||
method: 'GET',
|
||||
headers: { accept: 'multipart/mixed' },
|
||||
});
|
||||
const directiveBody = nullthrows(await getDirectiveBodyAsync(response));
|
||||
|
||||
checkDirectiveBodyAgainstUpdateInfoGroup(directiveBody);
|
||||
|
||||
const directiveSignature = signBody(directiveBody, codeSigningInfo);
|
||||
|
||||
await PublishMutation.setCodeSigningInfoAsync(graphqlClient, newUpdate.id, {
|
||||
alg: codeSigningInfo.codeSigningMetadata.alg,
|
||||
keyid: codeSigningInfo.codeSigningMetadata.keyid,
|
||||
sig: directiveSignature,
|
||||
});
|
||||
})
|
||||
);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return newUpdates;
|
||||
}
|
||||
|
||||
private static async selectRuntimeAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
{
|
||||
appId,
|
||||
branchName,
|
||||
batchSize = 5,
|
||||
}: {
|
||||
appId: string;
|
||||
branchName: string;
|
||||
batchSize?: number;
|
||||
}
|
||||
): Promise<RuntimeFragment | null> {
|
||||
const queryAsync = async (queryParams: QueryParams): Promise<Connection<RuntimeFragment>> => {
|
||||
return await RuntimeQuery.getRuntimesOnBranchAsync(graphqlClient, {
|
||||
appId,
|
||||
name: branchName,
|
||||
first: queryParams.first,
|
||||
after: queryParams.after,
|
||||
last: queryParams.last,
|
||||
before: queryParams.before,
|
||||
});
|
||||
};
|
||||
const getTitleAsync = async (runtime: RuntimeFragment): Promise<string> => {
|
||||
return runtime.version;
|
||||
};
|
||||
return await selectPaginatedAsync({
|
||||
queryAsync,
|
||||
getTitleAsync,
|
||||
printedType: 'target runtime',
|
||||
pageSize: batchSize,
|
||||
await publishRollBackToEmbeddedUpdateAsync({
|
||||
graphqlClient,
|
||||
projectId,
|
||||
exp,
|
||||
updateMessage,
|
||||
branch,
|
||||
codeSigningInfo,
|
||||
platforms: realizedPlatforms,
|
||||
runtimeVersion: selectedRuntime,
|
||||
json: jsonFlag,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ import { createProgressTracker } from '../utils/progress';
|
||||
|
||||
export default class BuildUpload extends EasCommand {
|
||||
static override description = 'upload a local build and generate a sharable link';
|
||||
static override hidden = true;
|
||||
|
||||
static override flags = {
|
||||
platform: Flags.enum<Platform.IOS | Platform.ANDROID>({
|
||||
|
||||
+75
-86
@@ -79,6 +79,8 @@ export type Account = {
|
||||
__typename?: 'Account';
|
||||
/** @deprecated Legacy access tokens are deprecated */
|
||||
accessTokens: Array<Maybe<AccessToken>>;
|
||||
/** Server account feature gate values for this account, optionally filtering by desired gates. */
|
||||
accountFeatureGates: Scalars['JSONObject']['output'];
|
||||
/** Coalesced project activity for all apps belonging to this account. */
|
||||
activityTimelineProjectActivities: Array<ActivityTimelineProjectActivity>;
|
||||
appCount: Scalars['Int']['output'];
|
||||
@@ -116,10 +118,6 @@ export type Account = {
|
||||
/** Billing information. Only visible to members with the ADMIN or OWNER role. */
|
||||
billing?: Maybe<Billing>;
|
||||
billingPeriod: BillingPeriod;
|
||||
/** (EAS Build) Builds associated with this account */
|
||||
builds: Array<Build>;
|
||||
/** Whether this account can enable SSO. */
|
||||
canEnableSSO: Scalars['Boolean']['output'];
|
||||
createdAt: Scalars['DateTime']['output'];
|
||||
displayName?: Maybe<Scalars['String']['output']>;
|
||||
/** Environment secrets for an account */
|
||||
@@ -191,6 +189,15 @@ export type Account = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An account is a container owning projects, credentials, billing and other organization
|
||||
* data and settings. Actors may own and be members of accounts.
|
||||
*/
|
||||
export type AccountAccountFeatureGatesArgs = {
|
||||
filter?: InputMaybe<Array<Scalars['String']['input']>>;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An account is a container owning projects, credentials, billing and other organization
|
||||
* data and settings. Actors may own and be members of accounts.
|
||||
@@ -362,18 +369,6 @@ export type AccountBillingPeriodArgs = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An account is a container owning projects, credentials, billing and other organization
|
||||
* data and settings. Actors may own and be members of accounts.
|
||||
*/
|
||||
export type AccountBuildsArgs = {
|
||||
limit: Scalars['Int']['input'];
|
||||
offset: Scalars['Int']['input'];
|
||||
platform?: InputMaybe<AppPlatform>;
|
||||
status?: InputMaybe<BuildStatus>;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An account is a container owning projects, credentials, billing and other organization
|
||||
* data and settings. Actors may own and be members of accounts.
|
||||
@@ -2419,6 +2414,16 @@ export type AppleDistributionCertificateMutationDeleteAppleDistributionCertifica
|
||||
id: Scalars['ID']['input'];
|
||||
};
|
||||
|
||||
export type AppleDistributionCertificateQuery = {
|
||||
__typename?: 'AppleDistributionCertificateQuery';
|
||||
byId: AppleDistributionCertificate;
|
||||
};
|
||||
|
||||
|
||||
export type AppleDistributionCertificateQueryByIdArgs = {
|
||||
id: Scalars['ID']['input'];
|
||||
};
|
||||
|
||||
export type AppleProvisioningProfile = {
|
||||
__typename?: 'AppleProvisioningProfile';
|
||||
account: Account;
|
||||
@@ -2475,6 +2480,16 @@ export type AppleProvisioningProfileMutationUpdateAppleProvisioningProfileArgs =
|
||||
id: Scalars['ID']['input'];
|
||||
};
|
||||
|
||||
export type AppleProvisioningProfileQuery = {
|
||||
__typename?: 'AppleProvisioningProfileQuery';
|
||||
byId: AppleProvisioningProfile;
|
||||
};
|
||||
|
||||
|
||||
export type AppleProvisioningProfileQueryByIdArgs = {
|
||||
id: Scalars['ID']['input'];
|
||||
};
|
||||
|
||||
export type ApplePushKey = {
|
||||
__typename?: 'ApplePushKey';
|
||||
account: Account;
|
||||
@@ -2893,8 +2908,6 @@ export type Build = ActivityTimelineProjectActivity & BuildOrBuildJob & {
|
||||
/** Queue position is 1-indexed */
|
||||
initialQueuePosition?: Maybe<Scalars['Int']['output']>;
|
||||
initiatingActor?: Maybe<Actor>;
|
||||
/** @deprecated User type is deprecated */
|
||||
initiatingUser?: Maybe<User>;
|
||||
iosEnterpriseProvisioning?: Maybe<BuildIosEnterpriseProvisioning>;
|
||||
isForIosSimulator: Scalars['Boolean']['output'];
|
||||
isGitWorkingTreeDirty?: Maybe<Scalars['Boolean']['output']>;
|
||||
@@ -2963,6 +2976,7 @@ export type BuildAnnotation = {
|
||||
regexFlags?: Maybe<Scalars['String']['output']>;
|
||||
regexString: Scalars['String']['output'];
|
||||
title: Scalars['String']['output'];
|
||||
type: BuildAnnotationType;
|
||||
};
|
||||
|
||||
export type BuildAnnotationDataInput = {
|
||||
@@ -2973,6 +2987,7 @@ export type BuildAnnotationDataInput = {
|
||||
regexFlags?: InputMaybe<Scalars['String']['input']>;
|
||||
regexString: Scalars['String']['input'];
|
||||
title: Scalars['String']['input'];
|
||||
type: BuildAnnotationType;
|
||||
};
|
||||
|
||||
export type BuildAnnotationFiltersInput = {
|
||||
@@ -3005,6 +3020,12 @@ export type BuildAnnotationMutationUpdateBuildAnnotationArgs = {
|
||||
buildAnnotationId: Scalars['ID']['input'];
|
||||
};
|
||||
|
||||
export enum BuildAnnotationType {
|
||||
Error = 'ERROR',
|
||||
Info = 'INFO',
|
||||
Warning = 'WARNING'
|
||||
}
|
||||
|
||||
export type BuildAnnotationsQuery = {
|
||||
__typename?: 'BuildAnnotationsQuery';
|
||||
/** View build annotations */
|
||||
@@ -4208,6 +4229,7 @@ export enum EnvironmentSecretType {
|
||||
|
||||
export type EnvironmentVariable = {
|
||||
__typename?: 'EnvironmentVariable';
|
||||
/** @deprecated Environment variables are automatically linked to all apps */
|
||||
apps: Array<App>;
|
||||
createdAt: Scalars['DateTime']['output'];
|
||||
environments?: Maybe<Array<EnvironmentVariableEnvironment>>;
|
||||
@@ -4254,12 +4276,6 @@ export type EnvironmentVariableMutation = {
|
||||
deleteBulkEnvironmentVariables: Array<DeleteEnvironmentVariableResult>;
|
||||
/** Delete an environment variable */
|
||||
deleteEnvironmentVariable: DeleteEnvironmentVariableResult;
|
||||
/** Bulk link shared environment variables */
|
||||
linkBulkSharedEnvironmentVariables: Array<EnvironmentVariable>;
|
||||
/** Link shared environment variable */
|
||||
linkSharedEnvironmentVariable: EnvironmentVariable;
|
||||
/** Unlink shared environment variable */
|
||||
unlinkSharedEnvironmentVariable: EnvironmentVariable;
|
||||
/** Bulk update environment variables */
|
||||
updateBulkEnvironmentVariables: Array<EnvironmentVariable>;
|
||||
/** Update an environment variable */
|
||||
@@ -4301,25 +4317,6 @@ export type EnvironmentVariableMutationDeleteEnvironmentVariableArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type EnvironmentVariableMutationLinkBulkSharedEnvironmentVariablesArgs = {
|
||||
linkData: Array<LinkSharedEnvironmentVariableInput>;
|
||||
};
|
||||
|
||||
|
||||
export type EnvironmentVariableMutationLinkSharedEnvironmentVariableArgs = {
|
||||
appId: Scalars['ID']['input'];
|
||||
environment?: InputMaybe<EnvironmentVariableEnvironment>;
|
||||
environmentVariableId: Scalars['ID']['input'];
|
||||
};
|
||||
|
||||
|
||||
export type EnvironmentVariableMutationUnlinkSharedEnvironmentVariableArgs = {
|
||||
appId: Scalars['ID']['input'];
|
||||
environment?: InputMaybe<EnvironmentVariableEnvironment>;
|
||||
environmentVariableId: Scalars['ID']['input'];
|
||||
};
|
||||
|
||||
|
||||
export type EnvironmentVariableMutationUpdateBulkEnvironmentVariablesArgs = {
|
||||
environmentVariablesData: Array<UpdateEnvironmentVariableInput>;
|
||||
};
|
||||
@@ -5465,12 +5462,6 @@ export type LinkSentryInstallationToExpoAccountInput = {
|
||||
sentryOrgSlug: Scalars['String']['input'];
|
||||
};
|
||||
|
||||
export type LinkSharedEnvironmentVariableInput = {
|
||||
appId: Scalars['ID']['input'];
|
||||
environment?: InputMaybe<EnvironmentVariableEnvironment>;
|
||||
environmentVariableId: Scalars['ID']['input'];
|
||||
};
|
||||
|
||||
export type LocalBuildArchiveSourceInput = {
|
||||
bucketKey: Scalars['String']['input'];
|
||||
type: LocalBuildArchiveSourceType;
|
||||
@@ -6297,6 +6288,10 @@ export type RootQuery = {
|
||||
appStoreConnectApiKey: AppStoreConnectApiKeyQuery;
|
||||
/** Top-level query object for querying Apple Device registration requests. */
|
||||
appleDeviceRegistrationRequest: AppleDeviceRegistrationRequestQuery;
|
||||
/** Top-level query object for querying Apple distribution certificates. */
|
||||
appleDistributionCertificate?: Maybe<AppleDistributionCertificateQuery>;
|
||||
/** Top-level query object for querying Apple provisioning profiles. */
|
||||
appleProvisioningProfile?: Maybe<AppleProvisioningProfileQuery>;
|
||||
/** Top-level query object for querying Apple Teams. */
|
||||
appleTeam: AppleTeamQuery;
|
||||
asset: AssetQuery;
|
||||
@@ -6833,6 +6828,7 @@ export enum StatuspageServiceName {
|
||||
EasBuild = 'EAS_BUILD',
|
||||
EasSubmit = 'EAS_SUBMIT',
|
||||
EasUpdate = 'EAS_UPDATE',
|
||||
EasWorkflows = 'EAS_WORKFLOWS',
|
||||
GithubApiRequests = 'GITHUB_API_REQUESTS',
|
||||
GithubWebhooks = 'GITHUB_WEBHOOKS'
|
||||
}
|
||||
@@ -8686,9 +8682,15 @@ export type WorkflowArtifact = {
|
||||
id: Scalars['ID']['output'];
|
||||
jobRun: JobRun;
|
||||
name: Scalars['String']['output'];
|
||||
storageType: WorkflowArtifactStorageType;
|
||||
updatedAt: Scalars['DateTime']['output'];
|
||||
};
|
||||
|
||||
export enum WorkflowArtifactStorageType {
|
||||
Gcs = 'GCS',
|
||||
R2 = 'R2'
|
||||
}
|
||||
|
||||
export type WorkflowJob = {
|
||||
__typename?: 'WorkflowJob';
|
||||
approvals: Array<WorkflowJobApproval>;
|
||||
@@ -9079,13 +9081,6 @@ export type AppInfoQueryVariables = Exact<{
|
||||
|
||||
export type AppInfoQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, fullName: string } } };
|
||||
|
||||
export type ScheduleUpdateGroupDeletionMutationVariables = Exact<{
|
||||
group: Scalars['ID']['input'];
|
||||
}>;
|
||||
|
||||
|
||||
export type ScheduleUpdateGroupDeletionMutation = { __typename?: 'RootMutation', update: { __typename?: 'UpdateMutation', scheduleUpdateGroupDeletion: { __typename?: 'BackgroundJobReceipt', id: string, state: BackgroundJobState, tries: number, willRetry: boolean, resultId?: string | null, resultType: BackgroundJobResultType, resultData?: any | null, errorCode?: string | null, errorMessage?: string | null, createdAt: any, updatedAt: any } } };
|
||||
|
||||
export type CreateAndroidAppBuildCredentialsMutationVariables = Exact<{
|
||||
androidAppBuildCredentialsInput: AndroidAppBuildCredentialsInput;
|
||||
androidAppCredentialsId: Scalars['ID']['input'];
|
||||
@@ -9570,24 +9565,6 @@ export type DeleteEnvironmentSecretMutationVariables = Exact<{
|
||||
|
||||
export type DeleteEnvironmentSecretMutation = { __typename?: 'RootMutation', environmentSecret: { __typename?: 'EnvironmentSecretMutation', deleteEnvironmentSecret: { __typename?: 'DeleteEnvironmentSecretResult', id: string } } };
|
||||
|
||||
export type LinkSharedEnvironmentVariableMutationVariables = Exact<{
|
||||
appId: Scalars['ID']['input'];
|
||||
environment?: InputMaybe<EnvironmentVariableEnvironment>;
|
||||
environmentVariableId: Scalars['ID']['input'];
|
||||
}>;
|
||||
|
||||
|
||||
export type LinkSharedEnvironmentVariableMutation = { __typename?: 'RootMutation', environmentVariable: { __typename?: 'EnvironmentVariableMutation', linkSharedEnvironmentVariable: { __typename?: 'EnvironmentVariable', id: string, name: string, value?: string | null, environments?: Array<EnvironmentVariableEnvironment> | null, createdAt: any, updatedAt: any, scope: EnvironmentVariableScope, visibility?: EnvironmentVariableVisibility | null, type: EnvironmentSecretType } } };
|
||||
|
||||
export type UnlinkSharedEnvironmentVariableMutationVariables = Exact<{
|
||||
appId: Scalars['ID']['input'];
|
||||
environment?: InputMaybe<EnvironmentVariableEnvironment>;
|
||||
environmentVariableId: Scalars['ID']['input'];
|
||||
}>;
|
||||
|
||||
|
||||
export type UnlinkSharedEnvironmentVariableMutation = { __typename?: 'RootMutation', environmentVariable: { __typename?: 'EnvironmentVariableMutation', unlinkSharedEnvironmentVariable: { __typename?: 'EnvironmentVariable', id: string, name: string, value?: string | null, environments?: Array<EnvironmentVariableEnvironment> | null, createdAt: any, updatedAt: any, scope: EnvironmentVariableScope, visibility?: EnvironmentVariableVisibility | null, type: EnvironmentSecretType } } };
|
||||
|
||||
export type CreateEnvironmentVariableForAccountMutationVariables = Exact<{
|
||||
input: CreateSharedEnvironmentVariableInput;
|
||||
accountId: Scalars['ID']['input'];
|
||||
@@ -9661,7 +9638,7 @@ export type UpdatePublishMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type UpdatePublishMutation = { __typename?: 'RootMutation', updateBranch: { __typename?: 'UpdateBranchMutation', publishUpdateGroups: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }> } };
|
||||
export type UpdatePublishMutation = { __typename?: 'RootMutation', updateBranch: { __typename?: 'UpdateBranchMutation', publishUpdateGroups: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string, group: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }> } };
|
||||
|
||||
export type SetCodeSigningInfoMutationVariables = Exact<{
|
||||
updateId: Scalars['ID']['input'];
|
||||
@@ -9677,7 +9654,7 @@ export type SetRolloutPercentageMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type SetRolloutPercentageMutation = { __typename?: 'RootMutation', update: { __typename?: 'UpdateMutation', setRolloutPercentage: { __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null } } };
|
||||
export type SetRolloutPercentageMutation = { __typename?: 'RootMutation', update: { __typename?: 'UpdateMutation', setRolloutPercentage: { __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string, group: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null } } };
|
||||
|
||||
export type CreateAndroidSubmissionMutationVariables = Exact<{
|
||||
appId: Scalars['ID']['input'];
|
||||
@@ -9847,7 +9824,7 @@ export type BranchesByAppQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type BranchesByAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updates: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }> }> } } };
|
||||
export type BranchesByAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updates: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string, group: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }> }> } } };
|
||||
|
||||
export type BranchesBasicPaginatedOnAppQueryVariables = Exact<{
|
||||
appId: Scalars['String']['input'];
|
||||
@@ -9868,7 +9845,7 @@ export type ViewBranchesOnUpdateChannelQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ViewBranchesOnUpdateChannelQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateChannelByName?: { __typename?: 'UpdateChannel', id: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> }> } | null } } };
|
||||
export type ViewBranchesOnUpdateChannelQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateChannelByName?: { __typename?: 'UpdateChannel', id: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string, group: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> }> } | null } } };
|
||||
|
||||
export type BuildsByIdQueryVariables = Exact<{
|
||||
buildId: Scalars['ID']['input'];
|
||||
@@ -9916,7 +9893,7 @@ export type ViewUpdateChannelOnAppQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ViewUpdateChannelOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateChannelByName?: { __typename?: 'UpdateChannel', id: string, isPaused: boolean, name: string, updatedAt: any, createdAt: any, branchMapping: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> }> } | null } } };
|
||||
export type ViewUpdateChannelOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateChannelByName?: { __typename?: 'UpdateChannel', id: string, isPaused: boolean, name: string, updatedAt: any, createdAt: any, branchMapping: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string, group: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> }> } | null } } };
|
||||
|
||||
export type ViewUpdateChannelsOnAppQueryVariables = Exact<{
|
||||
appId: Scalars['String']['input'];
|
||||
@@ -9925,7 +9902,7 @@ export type ViewUpdateChannelsOnAppQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ViewUpdateChannelsOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateChannels: Array<{ __typename?: 'UpdateChannel', id: string, isPaused: boolean, name: string, updatedAt: any, createdAt: any, branchMapping: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> }> }> } } };
|
||||
export type ViewUpdateChannelsOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateChannels: Array<{ __typename?: 'UpdateChannel', id: string, isPaused: boolean, name: string, updatedAt: any, createdAt: any, branchMapping: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string, group: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> }> }> } } };
|
||||
|
||||
export type ViewUpdateChannelsPaginatedOnAppQueryVariables = Exact<{
|
||||
appId: Scalars['String']['input'];
|
||||
@@ -10061,7 +10038,7 @@ export type ViewUpdatesByGroupQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ViewUpdatesByGroupQuery = { __typename?: 'RootQuery', updatesByGroup: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }> };
|
||||
export type ViewUpdatesByGroupQuery = { __typename?: 'RootQuery', updatesByGroup: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string, group: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }> };
|
||||
|
||||
export type ViewUpdateGroupsOnBranchQueryVariables = Exact<{
|
||||
appId: Scalars['String']['input'];
|
||||
@@ -10072,7 +10049,7 @@ export type ViewUpdateGroupsOnBranchQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ViewUpdateGroupsOnBranchQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateBranchByName?: { __typename?: 'UpdateBranch', id: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> } | null } } };
|
||||
export type ViewUpdateGroupsOnBranchQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateBranchByName?: { __typename?: 'UpdateBranch', id: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string, group: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> } | null } } };
|
||||
|
||||
export type ViewUpdateGroupsOnAppQueryVariables = Exact<{
|
||||
appId: Scalars['String']['input'];
|
||||
@@ -10082,14 +10059,14 @@ export type ViewUpdateGroupsOnAppQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ViewUpdateGroupsOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> } } };
|
||||
export type ViewUpdateGroupsOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string, group: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> } } };
|
||||
|
||||
export type UpdateByIdQueryVariables = Exact<{
|
||||
updateId: Scalars['ID']['input'];
|
||||
}>;
|
||||
|
||||
|
||||
export type UpdateByIdQuery = { __typename?: 'RootQuery', updates: { __typename?: 'UpdateQuery', byId: { __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null } } };
|
||||
export type UpdateByIdQuery = { __typename?: 'RootQuery', updates: { __typename?: 'UpdateQuery', byId: { __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string, group: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null } } };
|
||||
|
||||
export type CurrentUserQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
@@ -10161,9 +10138,9 @@ export type StatuspageServiceFragment = { __typename?: 'StatuspageService', id:
|
||||
|
||||
export type SubmissionFragment = { __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logFiles: Array<string>, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null };
|
||||
|
||||
export type UpdateFragment = { __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null };
|
||||
export type UpdateFragment = { __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string, group: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null };
|
||||
|
||||
export type UpdateBranchFragment = { __typename?: 'UpdateBranch', id: string, name: string, updates: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }> };
|
||||
export type UpdateBranchFragment = { __typename?: 'UpdateBranch', id: string, name: string, updates: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, isGitWorkingTreeDirty: boolean, environment?: EnvironmentVariableEnvironment | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string, group: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }> };
|
||||
|
||||
export type UpdateBranchBasicInfoFragment = { __typename?: 'UpdateBranch', id: string, name: string };
|
||||
|
||||
@@ -10209,6 +10186,18 @@ export type CommonIosAppCredentialsWithoutBuildCredentialsFragment = { __typenam
|
||||
|
||||
export type CommonIosAppCredentialsFragment = { __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, name: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }, githubRepository?: { __typename?: 'GitHubRepository', id: string, metadata: { __typename?: 'GitHubRepositoryMetadata', githubRepoOwnerName: string, githubRepoName: string } } | null }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt: any }> } | null }>, app: { __typename?: 'App', id: string, name: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }, githubRepository?: { __typename?: 'GitHubRepository', id: string, metadata: { __typename?: 'GitHubRepositoryMetadata', githubRepoOwnerName: string, githubRepoName: string } } | null }, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string }, pushKey?: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, name: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }, githubRepository?: { __typename?: 'GitHubRepository', id: string, metadata: { __typename?: 'GitHubRepositoryMetadata', githubRepoOwnerName: string, githubRepoName: string } } | null }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } | null, appStoreConnectApiKeyForSubmissions?: { __typename?: 'AppStoreConnectApiKey', id: string, issuerIdentifier: string, keyIdentifier: string, name?: string | null, roles?: Array<AppStoreConnectUserRole> | null, createdAt: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null } | null };
|
||||
|
||||
export type ScheduleUpdateGroupDeletionMutationVariables = Exact<{
|
||||
group: Scalars['ID']['input'];
|
||||
}>;
|
||||
|
||||
|
||||
export type ScheduleUpdateGroupDeletionMutation = { __typename?: 'RootMutation', update: { __typename?: 'UpdateMutation', scheduleUpdateGroupDeletion: { __typename?: 'BackgroundJobReceipt', id: string, state: BackgroundJobState, tries: number, willRetry: boolean, resultId?: string | null, resultType: BackgroundJobResultType, resultData?: any | null, errorCode?: string | null, errorMessage?: string | null, createdAt: any, updatedAt: any } } };
|
||||
|
||||
export type MeUserActorQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type MeUserActorQuery = { __typename?: 'RootQuery', meUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null };
|
||||
|
||||
export type WorkerDeploymentFragment = { __typename?: 'WorkerDeployment', id: string, url: string, deploymentIdentifier: any, deploymentDomain: string, createdAt: any };
|
||||
|
||||
export type WorkerDeploymentAliasFragment = { __typename?: 'WorkerDeploymentAlias', id: string, aliasName?: any | null, url: string };
|
||||
|
||||
@@ -12,8 +12,6 @@ import {
|
||||
EnvironmentVariableEnvironment,
|
||||
EnvironmentVariableFragment,
|
||||
EnvironmentVariableVisibility,
|
||||
LinkSharedEnvironmentVariableMutation,
|
||||
UnlinkSharedEnvironmentVariableMutation,
|
||||
UpdateEnvironmentVariableMutation,
|
||||
} from '../generated';
|
||||
import { EnvironmentVariableFragmentNode } from '../types/EnvironmentVariable';
|
||||
@@ -37,76 +35,6 @@ export type EnvironmentVariablePushInput = {
|
||||
};
|
||||
|
||||
export const EnvironmentVariableMutation = {
|
||||
async linkSharedEnvironmentVariableAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
environmentVariableId: string,
|
||||
appId: string,
|
||||
environment?: EnvironmentVariableEnvironment
|
||||
): Promise<EnvironmentVariableFragment> {
|
||||
const data = await withErrorHandlingAsync(
|
||||
graphqlClient
|
||||
.mutation<LinkSharedEnvironmentVariableMutation>(
|
||||
gql`
|
||||
mutation LinkSharedEnvironmentVariable(
|
||||
$appId: ID!
|
||||
$environment: EnvironmentVariableEnvironment
|
||||
$environmentVariableId: ID!
|
||||
) {
|
||||
environmentVariable {
|
||||
linkSharedEnvironmentVariable(
|
||||
appId: $appId
|
||||
environmentVariableId: $environmentVariableId
|
||||
environment: $environment
|
||||
) {
|
||||
id
|
||||
...EnvironmentVariableFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
${print(EnvironmentVariableFragmentNode)}
|
||||
`,
|
||||
{ appId, environment, environmentVariableId }
|
||||
)
|
||||
.toPromise()
|
||||
);
|
||||
|
||||
return data.environmentVariable.linkSharedEnvironmentVariable;
|
||||
},
|
||||
async unlinkSharedEnvironmentVariableAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
environmentVariableId: string,
|
||||
appId: string,
|
||||
environment?: EnvironmentVariableEnvironment
|
||||
): Promise<EnvironmentVariableFragment> {
|
||||
const data = await withErrorHandlingAsync(
|
||||
graphqlClient
|
||||
.mutation<UnlinkSharedEnvironmentVariableMutation>(
|
||||
gql`
|
||||
mutation UnlinkSharedEnvironmentVariable(
|
||||
$appId: ID!
|
||||
$environment: EnvironmentVariableEnvironment
|
||||
$environmentVariableId: ID!
|
||||
) {
|
||||
environmentVariable {
|
||||
unlinkSharedEnvironmentVariable(
|
||||
appId: $appId
|
||||
environmentVariableId: $environmentVariableId
|
||||
environment: $environment
|
||||
) {
|
||||
id
|
||||
...EnvironmentVariableFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
${print(EnvironmentVariableFragmentNode)}
|
||||
`,
|
||||
{ appId, environment, environmentVariableId }
|
||||
)
|
||||
.toPromise()
|
||||
);
|
||||
|
||||
return data.environmentVariable.unlinkSharedEnvironmentVariable;
|
||||
},
|
||||
async createSharedVariableAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
input: CreateVariableArgs,
|
||||
|
||||
@@ -36,6 +36,7 @@ export const UpdateFragmentNode = gql`
|
||||
rolloutPercentage
|
||||
rolloutControlUpdate {
|
||||
id
|
||||
group
|
||||
}
|
||||
fingerprint {
|
||||
id
|
||||
|
||||
@@ -1099,6 +1099,7 @@ export async function getUpdateRolloutInfoGroupAsync(
|
||||
platforms: UpdatePublishPlatform[];
|
||||
}
|
||||
): Promise<UpdateRolloutInfoGroup> {
|
||||
// note that this could return control updates in different update groups if the update groups only have a single platform
|
||||
return Object.fromEntries(
|
||||
await Promise.all(
|
||||
platforms.map<Promise<[string, UpdateRolloutInfo]>>(async platform => {
|
||||
|
||||
@@ -70,7 +70,7 @@ async function assertSimulatorAppInstalledAsync(): Promise<void> {
|
||||
const simulatorAppId = await getSimulatorAppIdAsync();
|
||||
if (!simulatorAppId) {
|
||||
throw new Error(
|
||||
`Can't determine id of Simulator app; the Simulator is most likely not installed on this machine. Run 'sudo xcode-select -s /Applications/Xcode.app'`
|
||||
`Can't determine id of Simulator app; the Simulator is most likely not installed on this machine. Run 'sudo xcode-select -s /Applications/Xcode.app/Contents/Developer'`
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -305,20 +305,22 @@ async function ensureEASUpdateIsConfiguredNativelyAsync(
|
||||
export async function ensureEASUpdateIsConfiguredInEasJsonAsync(projectDir: string): Promise<void> {
|
||||
const easJsonPath = EasJsonAccessor.formatEasJsonPath(projectDir);
|
||||
|
||||
// Skip if eas.json doesn't exist.
|
||||
if (!(await fs.pathExists(easJsonPath))) {
|
||||
Log.warn(
|
||||
`EAS Build is not configured. If you'd like to use EAS Build with EAS Update, run ${chalk.bold(
|
||||
'eas build:configure'
|
||||
)}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add channel to all build profiles.
|
||||
try {
|
||||
const easJsonAccessor = EasJsonAccessor.fromProjectPath(projectDir);
|
||||
await easJsonAccessor.readRawJsonAsync();
|
||||
|
||||
easJsonAccessor.patch(easJsonRawObject => {
|
||||
// If there are no build profiles then we are done.
|
||||
if (!easJsonRawObject.build) {
|
||||
return easJsonRawObject;
|
||||
}
|
||||
|
||||
const easBuildProfilesWithChannels = Object.keys(easJsonRawObject.build).reduce(
|
||||
(acc, profileNameKey) => {
|
||||
const buildProfile = easJsonRawObject.build[profileNameKey];
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
|
||||
import { withErrorHandlingAsync } from '../graphql/client';
|
||||
import {
|
||||
BackgroundJobReceiptDataFragment,
|
||||
ScheduleUpdateGroupDeletionMutation,
|
||||
ScheduleUpdateGroupDeletionMutationVariables,
|
||||
} from '../graphql/generated';
|
||||
import { BackgroundJobReceiptNode } from '../graphql/types/BackgroundJobReceipt';
|
||||
|
||||
export async function scheduleUpdateGroupDeletionAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
{
|
||||
group,
|
||||
}: {
|
||||
group: string;
|
||||
}
|
||||
): Promise<BackgroundJobReceiptDataFragment> {
|
||||
const result = await withErrorHandlingAsync(
|
||||
graphqlClient
|
||||
.mutation<ScheduleUpdateGroupDeletionMutation, ScheduleUpdateGroupDeletionMutationVariables>(
|
||||
gql`
|
||||
mutation ScheduleUpdateGroupDeletion($group: ID!) {
|
||||
update {
|
||||
scheduleUpdateGroupDeletion(group: $group) {
|
||||
id
|
||||
...BackgroundJobReceiptData
|
||||
}
|
||||
}
|
||||
}
|
||||
${BackgroundJobReceiptNode}
|
||||
`,
|
||||
{ group }
|
||||
)
|
||||
.toPromise()
|
||||
);
|
||||
return result.update.scheduleUpdateGroupDeletion;
|
||||
}
|
||||
@@ -10,21 +10,27 @@ import {
|
||||
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
|
||||
import { PaginatedQueryOptions } from '../commandUtils/pagination';
|
||||
import {
|
||||
AppPlatform,
|
||||
RuntimeFragment,
|
||||
UpdateFragment,
|
||||
ViewUpdateGroupsOnAppQueryVariables,
|
||||
ViewUpdateGroupsOnBranchQueryVariables,
|
||||
} from '../graphql/generated';
|
||||
import { RuntimeQuery } from '../graphql/queries/RuntimeQuery';
|
||||
import { UpdateQuery } from '../graphql/queries/UpdateQuery';
|
||||
import Log from '../log';
|
||||
import { UpdatePublishPlatform } from '../project/publish';
|
||||
import formatFields from '../utils/formatFields';
|
||||
import { printJsonOnlyOutput } from '../utils/json';
|
||||
import {
|
||||
paginatedQueryWithConfirmPromptAsync,
|
||||
paginatedQueryWithSelectPromptAsync,
|
||||
} from '../utils/queries';
|
||||
import { Connection, QueryParams, selectPaginatedAsync } from '../utils/relay';
|
||||
|
||||
export const UPDATES_LIMIT = 50;
|
||||
export const UPDATE_GROUPS_LIMIT = 25;
|
||||
export const RUNTIME_VERSIONS_LIMIT = 25;
|
||||
|
||||
export async function listAndRenderUpdateGroupsOnAppAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
@@ -100,6 +106,58 @@ export async function listAndRenderUpdateGroupsOnBranchAsync(
|
||||
}
|
||||
}
|
||||
|
||||
export async function selectRuntimeAndGetLatestUpdateGroupForEachPublishPlatformOnBranchAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
{
|
||||
projectId,
|
||||
branchName,
|
||||
paginatedQueryOptions,
|
||||
}: {
|
||||
projectId: string;
|
||||
branchName: string;
|
||||
paginatedQueryOptions: PaginatedQueryOptions;
|
||||
}
|
||||
): Promise<Record<UpdatePublishPlatform, UpdateFragment[] | undefined>> {
|
||||
if (paginatedQueryOptions.nonInteractive) {
|
||||
throw new Error('Unable to select an update in non-interactive mode.');
|
||||
}
|
||||
|
||||
const runtimeVersion = await selectRuntimeOnBranchAsync(graphqlClient, {
|
||||
appId: projectId,
|
||||
branchName,
|
||||
});
|
||||
if (!runtimeVersion) {
|
||||
throw new Error('No runtime version selected.');
|
||||
}
|
||||
|
||||
return {
|
||||
ios: (
|
||||
await queryUpdateGroupsOnBranchAsync(graphqlClient, {
|
||||
appId: projectId,
|
||||
branchName,
|
||||
limit: 1,
|
||||
offset: 0,
|
||||
filter: {
|
||||
runtimeVersions: [runtimeVersion.version],
|
||||
platform: AppPlatform.Ios,
|
||||
},
|
||||
})
|
||||
)[0],
|
||||
android: (
|
||||
await queryUpdateGroupsOnBranchAsync(graphqlClient, {
|
||||
appId: projectId,
|
||||
branchName,
|
||||
limit: 1,
|
||||
offset: 0,
|
||||
filter: {
|
||||
runtimeVersions: [runtimeVersion.version],
|
||||
platform: AppPlatform.Android,
|
||||
},
|
||||
})
|
||||
)[0],
|
||||
};
|
||||
}
|
||||
|
||||
export async function selectUpdateGroupOnBranchAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
{
|
||||
@@ -230,3 +288,36 @@ function renderUpdateGroupsOnApp({
|
||||
.join(`\n\n${chalk.dim('———')}\n\n`)
|
||||
);
|
||||
}
|
||||
|
||||
export async function selectRuntimeOnBranchAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
{
|
||||
appId,
|
||||
branchName,
|
||||
batchSize = 5,
|
||||
}: {
|
||||
appId: string;
|
||||
branchName: string;
|
||||
batchSize?: number;
|
||||
}
|
||||
): Promise<RuntimeFragment | null> {
|
||||
const queryAsync = async (queryParams: QueryParams): Promise<Connection<RuntimeFragment>> => {
|
||||
return await RuntimeQuery.getRuntimesOnBranchAsync(graphqlClient, {
|
||||
appId,
|
||||
name: branchName,
|
||||
first: queryParams.first,
|
||||
after: queryParams.after,
|
||||
last: queryParams.last,
|
||||
before: queryParams.before,
|
||||
});
|
||||
};
|
||||
const getTitleAsync = async (runtime: RuntimeFragment): Promise<string> => {
|
||||
return runtime.version;
|
||||
};
|
||||
return await selectPaginatedAsync({
|
||||
queryAsync,
|
||||
getTitleAsync,
|
||||
printedType: 'target runtime',
|
||||
pageSize: batchSize,
|
||||
});
|
||||
}
|
||||
@@ -2,15 +2,26 @@ import { ExpoConfig } from '@expo/config';
|
||||
import assert from 'assert';
|
||||
import nullthrows from 'nullthrows';
|
||||
|
||||
import { getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync } from './getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync';
|
||||
import {
|
||||
selectRuntimeAndGetLatestUpdateGroupForEachPublishPlatformOnBranchAsync,
|
||||
selectUpdateGroupOnBranchAsync,
|
||||
} from './queries';
|
||||
import { truncateString as truncateUpdateMessage } from './utils';
|
||||
import { selectBranchOnAppAsync } from '../branch/queries';
|
||||
import { getUpdateGroupUrl } from '../build/utils/url';
|
||||
import { selectChannelOnAppAsync } from '../channel/queries';
|
||||
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
|
||||
import { getPaginatedQueryOptions } from '../commandUtils/pagination';
|
||||
import fetch from '../fetch';
|
||||
import { UpdateFragment, UpdateInfoGroup } from '../graphql/generated';
|
||||
import { PublishMutation } from '../graphql/mutations/PublishMutation';
|
||||
import { UpdateQuery } from '../graphql/queries/UpdateQuery';
|
||||
import Log, { link } from '../log';
|
||||
import { ora } from '../ora';
|
||||
import { getOwnerAccountForProjectIdAsync } from '../project/projectUtils';
|
||||
import { UpdatePublishPlatform, getUpdateRolloutInfoGroupAsync } from '../project/publish';
|
||||
import { promptAsync } from '../prompts';
|
||||
import {
|
||||
CodeSigningInfo,
|
||||
checkDirectiveBodyAgainstUpdateInfoGroup,
|
||||
@@ -265,3 +276,351 @@ export async function republishAsync({
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
type GetUpdateOrAskForUpdatesOptions = {
|
||||
nonInteractive: boolean;
|
||||
json: boolean;
|
||||
groupId?: string;
|
||||
branchName?: string;
|
||||
channelName?: string;
|
||||
};
|
||||
|
||||
export async function getUpdateGroupAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
groupId: string
|
||||
): Promise<UpdateToRepublish[]> {
|
||||
const updateGroup = await UpdateQuery.viewUpdateGroupAsync(graphqlClient, {
|
||||
groupId,
|
||||
});
|
||||
|
||||
return updateGroup.map(update => ({
|
||||
...update,
|
||||
groupId: update.group,
|
||||
branchId: update.branch.id,
|
||||
branchName: update.branch.name,
|
||||
}));
|
||||
}
|
||||
|
||||
type AskUpdateGroupForEachPublishPlatformFilteringByRuntimeVersionOptions = {
|
||||
nonInteractive: boolean;
|
||||
json: boolean;
|
||||
branchName?: string;
|
||||
channelName?: string;
|
||||
};
|
||||
|
||||
export async function askUpdateGroupForEachPublishPlatformFilteringByRuntimeVersionAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
projectId: string,
|
||||
options: AskUpdateGroupForEachPublishPlatformFilteringByRuntimeVersionOptions
|
||||
): Promise<Record<UpdatePublishPlatform, UpdateToRepublish[] | undefined>> {
|
||||
if (options.nonInteractive) {
|
||||
throw new Error('Must supply --group when in non-interactive mode');
|
||||
}
|
||||
|
||||
if (options.branchName) {
|
||||
return await askUpdateGroupForEachPublishPlatformFromBranchNameFilteringByRuntimeVersionAsync(
|
||||
graphqlClient,
|
||||
{
|
||||
...options,
|
||||
branchName: options.branchName,
|
||||
projectId,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (options.channelName) {
|
||||
return await askUpdateGroupForEachPublishPlatformFromChannelNameFilteringByRuntimeVersionAsync(
|
||||
graphqlClient,
|
||||
{
|
||||
...options,
|
||||
channelName: options.channelName,
|
||||
projectId,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const { choice } = await promptAsync({
|
||||
type: 'select',
|
||||
message: 'Find update by branch or channel?',
|
||||
name: 'choice',
|
||||
choices: [
|
||||
{ title: 'Branch', value: 'branch' },
|
||||
{ title: 'Channel', value: 'channel' },
|
||||
],
|
||||
});
|
||||
|
||||
if (choice === 'channel') {
|
||||
const { name } = await selectChannelOnAppAsync(graphqlClient, {
|
||||
projectId,
|
||||
selectionPromptTitle: 'Select a channel to view',
|
||||
paginatedQueryOptions: {
|
||||
json: options.json,
|
||||
nonInteractive: options.nonInteractive,
|
||||
offset: 0,
|
||||
},
|
||||
});
|
||||
|
||||
return await askUpdateGroupForEachPublishPlatformFromChannelNameFilteringByRuntimeVersionAsync(
|
||||
graphqlClient,
|
||||
{
|
||||
...options,
|
||||
channelName: name,
|
||||
projectId,
|
||||
}
|
||||
);
|
||||
} else if (choice === 'branch') {
|
||||
const { name } = await selectBranchOnAppAsync(graphqlClient, {
|
||||
projectId,
|
||||
promptTitle: 'Select branch from which to choose update',
|
||||
displayTextForListItem: updateBranch => ({
|
||||
title: updateBranch.name,
|
||||
}),
|
||||
// discard limit and offset because this query is not their intended target
|
||||
paginatedQueryOptions: {
|
||||
json: options.json,
|
||||
nonInteractive: options.nonInteractive,
|
||||
offset: 0,
|
||||
},
|
||||
});
|
||||
|
||||
return await askUpdateGroupForEachPublishPlatformFromBranchNameFilteringByRuntimeVersionAsync(
|
||||
graphqlClient,
|
||||
{
|
||||
...options,
|
||||
branchName: name,
|
||||
projectId,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
throw new Error('Must choose update via channel or branch');
|
||||
}
|
||||
}
|
||||
|
||||
export async function getUpdateGroupOrAskForUpdateGroupAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
projectId: string,
|
||||
options: GetUpdateOrAskForUpdatesOptions
|
||||
): Promise<UpdateToRepublish[]> {
|
||||
if (options.groupId) {
|
||||
return await getUpdateGroupAsync(graphqlClient, options.groupId);
|
||||
}
|
||||
|
||||
if (options.nonInteractive) {
|
||||
throw new Error('Must supply --group when in non-interactive mode');
|
||||
}
|
||||
|
||||
if (options.branchName) {
|
||||
return await askUpdatesFromBranchNameAsync(graphqlClient, {
|
||||
...options,
|
||||
branchName: options.branchName,
|
||||
projectId,
|
||||
});
|
||||
}
|
||||
|
||||
if (options.channelName) {
|
||||
return await askUpdatesFromChannelNameAsync(graphqlClient, {
|
||||
...options,
|
||||
channelName: options.channelName,
|
||||
projectId,
|
||||
});
|
||||
}
|
||||
|
||||
const { choice } = await promptAsync({
|
||||
type: 'select',
|
||||
message: 'Find update by branch or channel?',
|
||||
name: 'choice',
|
||||
choices: [
|
||||
{ title: 'Branch', value: 'branch' },
|
||||
{ title: 'Channel', value: 'channel' },
|
||||
],
|
||||
});
|
||||
|
||||
if (choice === 'channel') {
|
||||
const { name } = await selectChannelOnAppAsync(graphqlClient, {
|
||||
projectId,
|
||||
selectionPromptTitle: 'Select a channel to view',
|
||||
paginatedQueryOptions: {
|
||||
json: options.json,
|
||||
nonInteractive: options.nonInteractive,
|
||||
offset: 0,
|
||||
},
|
||||
});
|
||||
|
||||
return await askUpdatesFromChannelNameAsync(graphqlClient, {
|
||||
...options,
|
||||
channelName: name,
|
||||
projectId,
|
||||
});
|
||||
} else if (choice === 'branch') {
|
||||
const { name } = await selectBranchOnAppAsync(graphqlClient, {
|
||||
projectId,
|
||||
promptTitle: 'Select branch from which to choose update',
|
||||
displayTextForListItem: updateBranch => ({
|
||||
title: updateBranch.name,
|
||||
}),
|
||||
// discard limit and offset because this query is not their intended target
|
||||
paginatedQueryOptions: {
|
||||
json: options.json,
|
||||
nonInteractive: options.nonInteractive,
|
||||
offset: 0,
|
||||
},
|
||||
});
|
||||
|
||||
return await askUpdatesFromBranchNameAsync(graphqlClient, {
|
||||
...options,
|
||||
branchName: name,
|
||||
projectId,
|
||||
});
|
||||
} else {
|
||||
throw new Error('Must choose update via channel or branch');
|
||||
}
|
||||
}
|
||||
|
||||
async function askUpdateGroupForEachPublishPlatformFromBranchNameFilteringByRuntimeVersionAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
{
|
||||
projectId,
|
||||
branchName,
|
||||
json,
|
||||
nonInteractive,
|
||||
}: { projectId: string; branchName: string; json: boolean; nonInteractive: boolean }
|
||||
): Promise<Record<UpdatePublishPlatform, UpdateToRepublish[] | undefined>> {
|
||||
const publishPlatformToLatestUpdateGroup =
|
||||
await selectRuntimeAndGetLatestUpdateGroupForEachPublishPlatformOnBranchAsync(graphqlClient, {
|
||||
projectId,
|
||||
branchName,
|
||||
paginatedQueryOptions: getPaginatedQueryOptions({ json, 'non-interactive': nonInteractive }),
|
||||
});
|
||||
|
||||
return {
|
||||
ios: publishPlatformToLatestUpdateGroup.ios?.map(update => ({
|
||||
...update,
|
||||
groupId: update.group,
|
||||
branchId: update.branch.id,
|
||||
branchName: update.branch.name,
|
||||
})),
|
||||
android: publishPlatformToLatestUpdateGroup.android?.map(update => ({
|
||||
...update,
|
||||
groupId: update.group,
|
||||
branchId: update.branch.id,
|
||||
branchName: update.branch.name,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
async function askUpdatesFromBranchNameAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
{
|
||||
projectId,
|
||||
branchName,
|
||||
json,
|
||||
nonInteractive,
|
||||
}: { projectId: string; branchName: string; json: boolean; nonInteractive: boolean }
|
||||
): Promise<UpdateToRepublish[]> {
|
||||
const updateGroup = await selectUpdateGroupOnBranchAsync(graphqlClient, {
|
||||
projectId,
|
||||
branchName,
|
||||
paginatedQueryOptions: getPaginatedQueryOptions({ json, 'non-interactive': nonInteractive }),
|
||||
});
|
||||
|
||||
return updateGroup.map(update => ({
|
||||
...update,
|
||||
groupId: update.group,
|
||||
branchId: update.branch.id,
|
||||
branchName: update.branch.name,
|
||||
}));
|
||||
}
|
||||
|
||||
async function askUpdateGroupForEachPublishPlatformFromChannelNameFilteringByRuntimeVersionAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
{
|
||||
projectId,
|
||||
channelName,
|
||||
json,
|
||||
nonInteractive,
|
||||
}: { projectId: string; channelName: string; json: boolean; nonInteractive: boolean }
|
||||
): Promise<Record<UpdatePublishPlatform, UpdateToRepublish[] | undefined>> {
|
||||
const { branchName } = await getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync(
|
||||
graphqlClient,
|
||||
projectId,
|
||||
channelName
|
||||
);
|
||||
|
||||
return await askUpdateGroupForEachPublishPlatformFromBranchNameFilteringByRuntimeVersionAsync(
|
||||
graphqlClient,
|
||||
{
|
||||
projectId,
|
||||
branchName,
|
||||
json,
|
||||
nonInteractive,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async function askUpdatesFromChannelNameAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
{
|
||||
projectId,
|
||||
channelName,
|
||||
json,
|
||||
nonInteractive,
|
||||
}: { projectId: string; channelName: string; json: boolean; nonInteractive: boolean }
|
||||
): Promise<UpdateToRepublish[]> {
|
||||
const { branchName } = await getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync(
|
||||
graphqlClient,
|
||||
projectId,
|
||||
channelName
|
||||
);
|
||||
|
||||
return await askUpdatesFromBranchNameAsync(graphqlClient, {
|
||||
projectId,
|
||||
branchName,
|
||||
json,
|
||||
nonInteractive,
|
||||
});
|
||||
}
|
||||
|
||||
type GetOrAskUpdateMessageOptions = {
|
||||
updateMessage?: string;
|
||||
nonInteractive: boolean;
|
||||
json: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get or ask the user for the update (group) message for the republish
|
||||
*/
|
||||
export async function getOrAskUpdateMessageAsync(
|
||||
updateGroup: UpdateToRepublish[],
|
||||
options: GetOrAskUpdateMessageOptions
|
||||
): Promise<string> {
|
||||
if (options.updateMessage) {
|
||||
return sanitizeUpdateMessage(options.updateMessage);
|
||||
}
|
||||
|
||||
if (options.nonInteractive || options.json) {
|
||||
throw new Error('Must supply --message when in non-interactive mode');
|
||||
}
|
||||
|
||||
// This command only uses a single update group to republish, meaning these values are always identical
|
||||
const oldGroupId = updateGroup[0].groupId;
|
||||
const oldUpdateMessage = updateGroup[0].message;
|
||||
|
||||
const { updateMessage } = await promptAsync({
|
||||
type: 'text',
|
||||
name: 'updateMessage',
|
||||
message: 'Provide an update message.',
|
||||
initial: `Republish "${oldUpdateMessage!}" - group: ${oldGroupId}`,
|
||||
validate: (value: any) => (value ? true : 'Update message may not be empty.'),
|
||||
});
|
||||
|
||||
return sanitizeUpdateMessage(updateMessage);
|
||||
}
|
||||
|
||||
function sanitizeUpdateMessage(updateMessage: string): string {
|
||||
if (updateMessage !== truncateUpdateMessage(updateMessage, 1024)) {
|
||||
Log.warn('Update message exceeds the allowed 1024 character limit, truncated update message.');
|
||||
return truncateUpdateMessage(updateMessage, 1024);
|
||||
}
|
||||
|
||||
return updateMessage;
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
import { ExpoConfig } from '@expo/config';
|
||||
import nullthrows from 'nullthrows';
|
||||
|
||||
import { getUpdateJsonInfosForUpdates } from './utils';
|
||||
import { getUpdateGroupUrl } from '../build/utils/url';
|
||||
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
|
||||
import fetch from '../fetch';
|
||||
import { PublishUpdateGroupInput, UpdatePublishMutation } from '../graphql/generated';
|
||||
import { PublishMutation } from '../graphql/mutations/PublishMutation';
|
||||
import Log, { link } from '../log';
|
||||
import { ora } from '../ora';
|
||||
import { getOwnerAccountForProjectIdAsync } from '../project/projectUtils';
|
||||
import {
|
||||
RuntimeVersionInfo,
|
||||
UpdatePublishPlatform,
|
||||
getRuntimeToPlatformsAndFingerprintInfoMappingFromRuntimeVersionInfoObjects,
|
||||
} from '../project/publish';
|
||||
import {
|
||||
CodeSigningInfo,
|
||||
checkDirectiveBodyAgainstUpdateInfoGroup,
|
||||
getDirectiveBodyAsync,
|
||||
signBody,
|
||||
} from '../utils/code-signing';
|
||||
import uniqBy from '../utils/expodash/uniqBy';
|
||||
import formatFields from '../utils/formatFields';
|
||||
import { printJsonOnlyOutput } from '../utils/json';
|
||||
|
||||
export async function publishRollBackToEmbeddedUpdateAsync({
|
||||
graphqlClient,
|
||||
projectId,
|
||||
exp,
|
||||
updateMessage,
|
||||
branch,
|
||||
codeSigningInfo,
|
||||
platforms,
|
||||
runtimeVersion,
|
||||
json,
|
||||
}: {
|
||||
graphqlClient: ExpoGraphqlClient;
|
||||
projectId: string;
|
||||
exp: ExpoConfig;
|
||||
updateMessage: string | undefined;
|
||||
branch: { name: string; id: string };
|
||||
codeSigningInfo: CodeSigningInfo | undefined;
|
||||
platforms: UpdatePublishPlatform[];
|
||||
runtimeVersion: string;
|
||||
json: boolean;
|
||||
}): Promise<void> {
|
||||
const runtimeToPlatformsAndFingerprintInfoMapping =
|
||||
getRuntimeToPlatformsAndFingerprintInfoMappingFromRuntimeVersionInfoObjects(
|
||||
platforms.map(platform => ({
|
||||
platform,
|
||||
runtimeVersionInfo: {
|
||||
runtimeVersion,
|
||||
expoUpdatesRuntimeFingerprint: null,
|
||||
expoUpdatesRuntimeFingerprintHash: null,
|
||||
},
|
||||
}))
|
||||
);
|
||||
|
||||
let newUpdates: UpdatePublishMutation['updateBranch']['publishUpdateGroups'];
|
||||
const publishSpinner = ora('Publishing...').start();
|
||||
try {
|
||||
newUpdates = await publishRollbacksAsync({
|
||||
graphqlClient,
|
||||
updateMessage,
|
||||
branchId: branch.id,
|
||||
codeSigningInfo,
|
||||
runtimeToPlatformsAndFingerprintInfoMapping,
|
||||
platforms,
|
||||
});
|
||||
publishSpinner.succeed('Published!');
|
||||
} catch (e) {
|
||||
publishSpinner.fail('Failed to publish updates');
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (json) {
|
||||
printJsonOnlyOutput(getUpdateJsonInfosForUpdates(newUpdates));
|
||||
} else {
|
||||
Log.addNewLineIfNone();
|
||||
|
||||
for (const runtime of uniqBy(
|
||||
runtimeToPlatformsAndFingerprintInfoMapping,
|
||||
version => version.runtimeVersion
|
||||
)) {
|
||||
const newUpdatesForRuntimeVersion = newUpdates.filter(
|
||||
update => update.runtimeVersion === runtime.runtimeVersion
|
||||
);
|
||||
if (newUpdatesForRuntimeVersion.length === 0) {
|
||||
throw new Error(
|
||||
`Publish response is missing updates with runtime ${runtime.runtimeVersion}.`
|
||||
);
|
||||
}
|
||||
const platforms = newUpdatesForRuntimeVersion.map(update => update.platform);
|
||||
const newAndroidUpdate = newUpdatesForRuntimeVersion.find(
|
||||
update => update.platform === 'android'
|
||||
);
|
||||
const newIosUpdate = newUpdatesForRuntimeVersion.find(update => update.platform === 'ios');
|
||||
const updateGroupId = newUpdatesForRuntimeVersion[0].group;
|
||||
|
||||
const projectName = exp.slug;
|
||||
const accountName = (await getOwnerAccountForProjectIdAsync(graphqlClient, projectId)).name;
|
||||
const updateGroupUrl = getUpdateGroupUrl(accountName, projectName, updateGroupId);
|
||||
const updateGroupLink = link(updateGroupUrl, { dim: false });
|
||||
|
||||
Log.log(
|
||||
formatFields([
|
||||
{ label: 'Branch', value: branch.name },
|
||||
{ label: 'Runtime version', value: runtime.runtimeVersion },
|
||||
{ label: 'Platform', value: platforms.join(', ') },
|
||||
{ label: 'Update group ID', value: updateGroupId },
|
||||
...(newAndroidUpdate ? [{ label: 'Android update ID', value: newAndroidUpdate.id }] : []),
|
||||
...(newIosUpdate ? [{ label: 'iOS update ID', value: newIosUpdate.id }] : []),
|
||||
{ label: 'Message', value: updateMessage ?? '' },
|
||||
{ label: 'EAS Dashboard', value: updateGroupLink },
|
||||
])
|
||||
);
|
||||
Log.addNewLineIfNone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function publishRollbacksAsync({
|
||||
graphqlClient,
|
||||
updateMessage,
|
||||
branchId,
|
||||
codeSigningInfo,
|
||||
runtimeToPlatformsAndFingerprintInfoMapping,
|
||||
platforms,
|
||||
}: {
|
||||
graphqlClient: ExpoGraphqlClient;
|
||||
updateMessage: string | undefined;
|
||||
branchId: string;
|
||||
codeSigningInfo: CodeSigningInfo | undefined;
|
||||
runtimeToPlatformsAndFingerprintInfoMapping: (RuntimeVersionInfo & {
|
||||
platforms: UpdatePublishPlatform[];
|
||||
})[];
|
||||
platforms: UpdatePublishPlatform[];
|
||||
}): Promise<UpdatePublishMutation['updateBranch']['publishUpdateGroups']> {
|
||||
const rollbackInfoGroups = Object.fromEntries(platforms.map(platform => [platform, true]));
|
||||
|
||||
// Sort the updates into different groups based on their platform specific runtime versions
|
||||
const updateGroups: PublishUpdateGroupInput[] = runtimeToPlatformsAndFingerprintInfoMapping.map(
|
||||
({ runtimeVersion, platforms }) => {
|
||||
const localRollbackInfoGroup = Object.fromEntries(
|
||||
platforms.map(platform => [platform, rollbackInfoGroups[platform]])
|
||||
);
|
||||
|
||||
return {
|
||||
branchId,
|
||||
rollBackToEmbeddedInfoGroup: localRollbackInfoGroup,
|
||||
runtimeVersion,
|
||||
message: updateMessage,
|
||||
awaitingCodeSigningInfo: !!codeSigningInfo,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const newUpdates = await PublishMutation.publishUpdateGroupAsync(graphqlClient, updateGroups);
|
||||
|
||||
if (codeSigningInfo) {
|
||||
Log.log('🔒 Signing roll back');
|
||||
|
||||
const updatesTemp = [...newUpdates];
|
||||
const updateGroupsAndTheirUpdates = updateGroups.map(updateGroup => {
|
||||
const newUpdates = updatesTemp.splice(
|
||||
0,
|
||||
Object.keys(nullthrows(updateGroup.rollBackToEmbeddedInfoGroup)).length
|
||||
);
|
||||
return {
|
||||
updateGroup,
|
||||
newUpdates,
|
||||
};
|
||||
});
|
||||
|
||||
await Promise.all(
|
||||
updateGroupsAndTheirUpdates.map(async ({ newUpdates }) => {
|
||||
await Promise.all(
|
||||
newUpdates.map(async newUpdate => {
|
||||
const response = await fetch(newUpdate.manifestPermalink, {
|
||||
method: 'GET',
|
||||
headers: { accept: 'multipart/mixed' },
|
||||
});
|
||||
const directiveBody = nullthrows(await getDirectiveBodyAsync(response));
|
||||
|
||||
checkDirectiveBodyAgainstUpdateInfoGroup(directiveBody);
|
||||
|
||||
const directiveSignature = signBody(directiveBody, codeSigningInfo);
|
||||
|
||||
await PublishMutation.setCodeSigningInfoAsync(graphqlClient, newUpdate.id, {
|
||||
alg: codeSigningInfo.codeSigningMetadata.alg,
|
||||
keyid: codeSigningInfo.codeSigningMetadata.keyid,
|
||||
sig: directiveSignature,
|
||||
});
|
||||
})
|
||||
);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return newUpdates;
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
import { createGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
|
||||
import { withErrorHandlingAsync } from '../graphql/client';
|
||||
import { MeUserActorQuery, MeUserActorQueryVariables } from '../graphql/generated';
|
||||
|
||||
export async function fetchUserAsync({
|
||||
sessionSecret,
|
||||
@@ -8,26 +10,30 @@ export async function fetchUserAsync({
|
||||
sessionSecret: string;
|
||||
}): Promise<{ id: string; username: string }> {
|
||||
const graphqlClient = createGraphqlClient({ accessToken: null, sessionSecret });
|
||||
const result = await graphqlClient
|
||||
.query(
|
||||
gql`
|
||||
query UserQuery {
|
||||
meUserActor {
|
||||
id
|
||||
username
|
||||
const result = await withErrorHandlingAsync(
|
||||
graphqlClient
|
||||
.query<MeUserActorQuery, MeUserActorQueryVariables>(
|
||||
gql`
|
||||
query MeUserActorQuery {
|
||||
meUserActor {
|
||||
id
|
||||
username
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
{},
|
||||
{
|
||||
additionalTypenames: [] /* UserQuery has immutable fields */,
|
||||
}
|
||||
)
|
||||
.toPromise();
|
||||
`,
|
||||
{},
|
||||
{ additionalTypenames: ['UserActor'] }
|
||||
)
|
||||
.toPromise()
|
||||
);
|
||||
|
||||
const meUserActor = result.meUserActor;
|
||||
if (!meUserActor) {
|
||||
throw new Error('Failed to fetch user data after login.');
|
||||
}
|
||||
|
||||
const { data } = result;
|
||||
return {
|
||||
id: data.meUserActor.id,
|
||||
username: data.meUserActor.username,
|
||||
id: meUserActor.id,
|
||||
username: meUserActor.username,
|
||||
};
|
||||
}
|
||||
@@ -26,6 +26,7 @@ const humanReadableServiceName: Record<StatuspageServiceName, string> = {
|
||||
[StatuspageServiceName.EasUpdate]: 'EAS Update',
|
||||
[StatuspageServiceName.GithubApiRequests]: 'GitHub API Requests',
|
||||
[StatuspageServiceName.GithubWebhooks]: 'Github Webhooks',
|
||||
[StatuspageServiceName.EasWorkflows]: 'EAS Workflows',
|
||||
};
|
||||
|
||||
function warnAboutServiceOutage(service: StatuspageServiceFragment): void {
|
||||
|
||||
Reference in new issue
Block a user