Compare commits

..
Author SHA1 Message Date
Douglas Lowder b3bba882b1 Add mutation for getting workflows from git ref 2025-11-20 16:30:50 -08:00
Expo CI 4476c87962 update CHANGELOG.md 2025-11-20 19:58:01 +00:00
Expo CI 18ecd0844a v16.28.0 2025-11-20 19:39:20 +00:00
Colin MacKenzie cc3e7cdbe4 remove package json changes (#3263) 2025-11-20 13:36:15 -06:00
Colin MacKenzie aa7fecb9fe [eas-cli] Fix usage warning bug in eas:build (#3260)
* fix overages bug

* stub changelog

* update pr number

* fix test
2025-11-20 13:24:00 -06:00
Douglas Lowder c73a3e3a1e Update GraphQL from server, fix type error in test (#3262)
# Why

GraphQL test started failing today after a recent server change in updates GraphQL queries. Failed test run at https://github.com/expo/eas-cli/actions/runs/19529909252

# How

- Updated GraphQL generated code
- Fixed a TS type error in one test

# Test Plan

- CI should pass
2025-11-20 11:18:21 -08:00
Quinlan Jung 🦥 37ca2ebd55 [ENG-17987][eas-cli] delete branch in background (#3258)
* [eas-cli] delete branch in background

* Temporary Commit at 11/18/2025, 4:28:38 PM
2025-11-18 16:33:40 -08:00
Colin MacKenzie dead11964e [eas-cli] Sort organization accounts first in eas:new (#3256)
* sort accounts

* update changelog

* fix failing test
2025-11-17 13:44:50 -06:00
Expo CI b66d31d7d7 update CHANGELOG.md 2025-11-13 02:21:00 +00:00
Expo CI ed8170047b v16.27.0 2025-11-13 02:14:02 +00:00
Quinlan Jung 🦥 0e4056ba82 [eas-cli] kick off update patch generation if enabled (#3250)
* [eas-cli] kick off update patch generation if enabled

* Temporary Commit at 11/5/2025, 3:09:27 PM

* Temporary Commit at 11/5/2025, 3:19:31 PM

* Temporary Commit at 11/5/2025, 3:25:14 PM

* Temporary Commit at 11/11/2025, 2:06:29 PM

* Temporary Commit at 11/11/2025, 2:51:21 PM

* Temporary Commit at 11/11/2025, 2:53:51 PM

* Temporary Commit at 11/11/2025, 4:27:57 PM

* Temporary Commit at 11/12/2025, 5:31:14 PM
2025-11-12 18:05:53 -08:00
Kudo Chien 6182ea5a1d [eas-cli] remove plugins evaluation from workflow:run (#3254) 2025-11-12 01:46:16 +08:00
Douglas Lowder c9e7b649ad Fix workflow:status when run ID passed in (#3253)
# Why

In `workflow:status`, the argument name for the passed-in workflow run ID is incorrect. Instead of showing the status of that run, it shows the dialog to select from recent runs.

# How

Fixed the argument name.

# Test Plan

Works when testing locally.
2025-11-10 01:55:11 -08:00
Quinlan Jung 🦥 7a6b796242 [eas-cli] fix yarn watch (#3251)
* [eas-cli] fix yarn watch

* Temporary Commit at 11/6/2025, 12:22:09 PM
2025-11-06 12:37:12 -08:00
Kadi Kraman 804eb9a326 [eas-cli] Fix updating file env vars with env:update --non-interactive (#3249) 2025-11-05 12:12:40 +00:00
Expo CI 8da14f0101 update CHANGELOG.md 2025-10-29 19:26:44 +00:00
Expo CI dc62d22816 v16.26.0 2025-10-29 19:17:21 +00:00
Colin MacKenzie 258c625611 [eas-cli] eas:new - remove hidden tag; update output and project README (#3243)
* fix typo in the readme, change output formatting

* remove hidden flag

* update readme

* remove dev code
2025-10-29 14:10:30 -05:00
Douglas Lowder e84340774d New command workflow:status (#3242)
# Why

Shows the status of a workflow run that has already started.

If the run is in progress, and the `--wait` flag is set, the command will show periodic updates on running jobs, the current job steps, and recent log lines, similarly to `eas workflow:run --wait`.

Otherwise, the command immediately returns with information on the run result, exactly as `eas workflow:run --wait` will show at the end of a run. If the run failed, the failed jobs, failed steps, and last few log lines are shown.

```bash
USAGE
  $ eas workflow:status [WORKFLOW_RUN_ID] [--non-interactive] [--wait] [--json]

ARGUMENTS
  WORKFLOW_RUN_ID  A workflow run ID.

FLAGS
  --json             Enable JSON output, non-JSON messages will be printed to stderr.
  --non-interactive  Run the command in non-interactive mode.
  --[no-]wait        Wait for workflow run to complete. Defaults to false.

DESCRIPTION
  show the status of an existing workflow run. If no run ID is provided, you will be prompted to select from recent
  workflow runs for the current project.

FLAG DESCRIPTIONS
  --[no-]wait  Wait for workflow run to complete. Defaults to false.

    Exit codes: 0 = success, 11 = failure, 12 = canceled, 13 = wait aborted.
```

# How

Leverages utility code already written for `eas workflow:run` and `eas workflow:logs`.

# Test Plan

- Tested on running and completed workflow runs.
- CI should pass.
2025-10-29 12:00:07 -07:00
Expo CI fbc23f7a7d update CHANGELOG.md 2025-10-28 15:05:45 +00:00
Expo CI 97255ec90d v16.25.1 2025-10-28 13:14:43 +00:00
Phil Pluckthun cfccc87b82 [eas-cli] Remove preview log output from EAS Hosting commands (#3241)
* Remove preview labels from EAS Hosting commands

* Add CHANGELOG entry
2025-10-27 22:25:44 +00:00
Expo CI 09b4f8367e update CHANGELOG.md 2025-10-27 16:55:04 +00:00
40 changed files with 3977 additions and 355 deletions

No files matched your search

+54 -1
View File
@@ -8,8 +8,61 @@ This is the log of notable changes to EAS CLI and related packages.
### 🎉 New features
- `eas:new` command changes (project name prompt, output cleanup, additional project files, additional prompts). ([#3235](https://github.com/expo/eas-cli/pull/3235) by [@mackenco](https://github.com/mackenco))
### 🐛 Bug fixes
### 🧹 Chores
## [16.28.0](https://github.com/expo/eas-cli/releases/tag/v16.28.0) - 2025-11-20
### 🎉 New features
- `eas:new` sorts organization accounts first in account selection. ([#3256](https://github.com/expo/eas-cli/pull/3256) by [@mackenco](https://github.com/mackenco))
### 🐛 Bug fixes
- Fix `eas:build` bug where overages are checked before config is ready. ([#3260](https://github.com/expo/eas-cli/pull/3260) by [@mackenco](https://github.com/mackenco))
### 🧹 Chores
- Delete branch in background. ([#3258](https://github.com/expo/eas-cli/pull/3258) by [@quinlanj](https://github.com/quinlanj))
## [16.27.0](https://github.com/expo/eas-cli/releases/tag/v16.27.0) - 2025-11-13
### 🎉 New features
- Kick off update patch generation if enabled - this is feature is in preview, don't use it for prod yet please. ([#3250](https://github.com/expo/eas-cli/pull/3250) by [@quinlanj](https://github.com/quinlanj))
### 🐛 Bug fixes
- Fix workflow:status when run ID passed in. ([#3253](https://github.com/expo/eas-cli/pull/3253) by [@douglowder](https://github.com/douglowder))
- Fix updating file env vars with `env:update --non-interactive`. ([#3249](https://github.com/expo/eas-cli/pull/3249) by [@kadikraman](https://github.com/kadikraman))
### 🧹 Chores
- Fix yarn watch. ([#3251](https://github.com/expo/eas-cli/pull/3251) by [@quinlanj](https://github.com/quinlanj))
- Remove the **node_modules** installation requirement for `workflow:run` command. ([#3254](https://github.com/expo/eas-cli/pull/3254) by [@kudo](https://github.com/kudo))
## [16.26.0](https://github.com/expo/eas-cli/releases/tag/v16.26.0) - 2025-10-29
### 🎉 New features
- New command `workflow:status`. ([#3242](https://github.com/expo/eas-cli/pull/3242) by [@douglowder](https://github.com/douglowder))
### 🧹 Chores
- `eas:new` cleanup (remove `hidden` tag, fix README error, output cleanup). ([#3243](https://github.com/expo/eas-cli/pull/3243) by [@mackenco](https://github.com/mackenco))
## [16.25.1](https://github.com/expo/eas-cli/releases/tag/v16.25.1) - 2025-10-28
### 🧹 Chores
- Remove preview label from EAS Hosting commands ([#3241](https://github.com/expo/eas-cli/pull/3241) by [@kitten](https://github.com/kitten))
## [16.25.0](https://github.com/expo/eas-cli/releases/tag/v16.25.0) - 2025-10-27
### 🎉 New features
- `eas:new` command changes (project name prompt, output cleanup, additional project files, additional prompts). ([#3235](https://github.com/expo/eas-cli/pull/3235) by [@mackenco](https://github.com/mackenco))
- `eas:build` command displays a warning when account is near it's build limit. ([#3236](https://github.com/expo/eas-cli/pull/3236) by [@mackenco](https://github.com/mackenco))
### 🐛 Bug fixes
+1 -1
View File
@@ -1,5 +1,5 @@
{
"npmClient": "yarn",
"version": "16.25.0",
"version": "16.28.0",
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
}
+160 -85
View File
@@ -120,10 +120,12 @@ eas --help COMMAND
* [`eas metadata:lint`](#eas-metadatalint)
* [`eas metadata:pull`](#eas-metadatapull)
* [`eas metadata:push`](#eas-metadatapush)
* [`eas new [PATH]`](#eas-new-path)
* [`eas onboarding [TARGET_PROJECT_DIRECTORY]`](#eas-onboarding-target_project_directory)
* [`eas open`](#eas-open)
* [`eas project:info`](#eas-projectinfo)
* [`eas project:init`](#eas-projectinit)
* [`eas project:new [PATH]`](#eas-projectnew-path)
* [`eas project:onboarding [TARGET_PROJECT_DIRECTORY]`](#eas-projectonboarding-target_project_directory)
* [`eas submit`](#eas-submit)
* [`eas update`](#eas-update)
@@ -152,6 +154,7 @@ eas --help COMMAND
* [`eas workflow:logs [ID]`](#eas-workflowlogs-id)
* [`eas workflow:run [FILE]`](#eas-workflowrun-file)
* [`eas workflow:runs`](#eas-workflowruns)
* [`eas workflow:status [WORKFLOW_RUN_ID]`](#eas-workflowstatus-workflow_run_id)
* [`eas workflow:validate PATH`](#eas-workflowvalidate-path)
* [`eas workflow:view [ID]`](#eas-workflowview-id)
@@ -173,7 +176,7 @@ ALIASES
$ eas login
```
_See code: [packages/eas-cli/src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/account/login.ts)_
## `eas account:logout`
@@ -190,7 +193,7 @@ ALIASES
$ eas logout
```
_See code: [packages/eas-cli/src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/account/logout.ts)_
## `eas account:view`
@@ -207,7 +210,7 @@ ALIASES
$ eas whoami
```
_See code: [packages/eas-cli/src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/account/view.ts)_
## `eas analytics [STATUS]`
@@ -221,7 +224,7 @@ DESCRIPTION
display or change analytics settings
```
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v16.25.0/packages/eas-cli/src/commands/analytics.ts)_
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v16.28.0/packages/eas-cli/src/commands/analytics.ts)_
## `eas autocomplete [SHELL]`
@@ -273,7 +276,7 @@ DESCRIPTION
create a branch
```
_See code: [packages/eas-cli/src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/branch/create.ts)_
## `eas branch:delete [NAME]`
@@ -294,7 +297,7 @@ DESCRIPTION
delete a branch
```
_See code: [packages/eas-cli/src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/branch/delete.ts)_
## `eas branch:list`
@@ -314,7 +317,7 @@ DESCRIPTION
list all branches
```
_See code: [packages/eas-cli/src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/branch/list.ts)_
## `eas branch:rename`
@@ -334,7 +337,7 @@ DESCRIPTION
rename a branch
```
_See code: [packages/eas-cli/src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/branch/rename.ts)_
## `eas branch:view [NAME]`
@@ -357,7 +360,7 @@ DESCRIPTION
view a branch
```
_See code: [packages/eas-cli/src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/branch/view.ts)_
## `eas build`
@@ -398,7 +401,7 @@ DESCRIPTION
start a build
```
_See code: [packages/eas-cli/src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/build/index.ts)_
## `eas build:cancel [BUILD_ID]`
@@ -417,7 +420,7 @@ DESCRIPTION
cancel a build
```
_See code: [packages/eas-cli/src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/build/cancel.ts)_
## `eas build:configure`
@@ -434,7 +437,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.25.0/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.28.0/packages/eas-cli/src/commands/build/configure.ts)_
## `eas build:delete [BUILD_ID]`
@@ -453,7 +456,7 @@ DESCRIPTION
delete a build
```
_See code: [packages/eas-cli/src/commands/build/delete.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/build/delete.ts)_
## `eas build:dev`
@@ -473,7 +476,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.25.0/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.28.0/packages/eas-cli/src/commands/build/dev.ts)_
## `eas build:download`
@@ -494,7 +497,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.25.0/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.28.0/packages/eas-cli/src/commands/build/download.ts)_
## `eas build:inspect`
@@ -529,7 +532,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.25.0/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.28.0/packages/eas-cli/src/commands/build/inspect.ts)_
## `eas build:list`
@@ -581,7 +584,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.25.0/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.28.0/packages/eas-cli/src/commands/build/list.ts)_
## `eas build:resign`
@@ -610,7 +613,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.25.0/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.28.0/packages/eas-cli/src/commands/build/resign.ts)_
## `eas build:run`
@@ -636,7 +639,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.25.0/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.28.0/packages/eas-cli/src/commands/build/run.ts)_
## `eas build:submit`
@@ -690,7 +693,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.25.0/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.28.0/packages/eas-cli/src/commands/build/version/get.ts)_
## `eas build:version:set`
@@ -709,7 +712,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.25.0/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.28.0/packages/eas-cli/src/commands/build/version/set.ts)_
## `eas build:version:sync`
@@ -728,7 +731,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.25.0/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.28.0/packages/eas-cli/src/commands/build/version/sync.ts)_
## `eas build:view [BUILD_ID]`
@@ -745,7 +748,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.25.0/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.28.0/packages/eas-cli/src/commands/build/view.ts)_
## `eas channel:create [NAME]`
@@ -766,7 +769,7 @@ DESCRIPTION
create a channel
```
_See code: [packages/eas-cli/src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/channel/create.ts)_
## `eas channel:delete [NAME]`
@@ -787,7 +790,7 @@ DESCRIPTION
Delete a channel
```
_See code: [packages/eas-cli/src/commands/channel/delete.ts](https://github.com/expo/eas-cli/blob/v16.25.0/packages/eas-cli/src/commands/channel/delete.ts)_
_See code: [packages/eas-cli/src/commands/channel/delete.ts](https://github.com/expo/eas-cli/blob/v16.28.0/packages/eas-cli/src/commands/channel/delete.ts)_
## `eas channel:edit [NAME]`
@@ -809,7 +812,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.25.0/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.28.0/packages/eas-cli/src/commands/channel/edit.ts)_
## `eas channel:list`
@@ -829,7 +832,7 @@ DESCRIPTION
list all channels
```
_See code: [packages/eas-cli/src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/channel/list.ts)_
## `eas channel:pause [NAME]`
@@ -851,7 +854,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.25.0/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.28.0/packages/eas-cli/src/commands/channel/pause.ts)_
## `eas channel:resume [NAME]`
@@ -873,7 +876,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.25.0/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.28.0/packages/eas-cli/src/commands/channel/resume.ts)_
## `eas channel:rollout [CHANNEL]`
@@ -906,7 +909,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.25.0/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.28.0/packages/eas-cli/src/commands/channel/rollout.ts)_
## `eas channel:view [NAME]`
@@ -929,7 +932,7 @@ DESCRIPTION
view a channel
```
_See code: [packages/eas-cli/src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/channel/view.ts)_
## `eas config`
@@ -950,7 +953,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.25.0/packages/eas-cli/src/commands/config.ts)_
_See code: [packages/eas-cli/src/commands/config.ts](https://github.com/expo/eas-cli/blob/v16.28.0/packages/eas-cli/src/commands/config.ts)_
## `eas credentials`
@@ -967,7 +970,7 @@ DESCRIPTION
manage credentials
```
_See code: [packages/eas-cli/src/commands/credentials/index.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/credentials/index.ts)_
## `eas credentials:configure-build`
@@ -985,7 +988,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.25.0/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.28.0/packages/eas-cli/src/commands/credentials/configure-build.ts)_
## `eas deploy [options]`
@@ -1013,7 +1016,7 @@ ALIASES
$ eas worker:deploy
```
_See code: [packages/eas-cli/src/commands/deploy/index.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/deploy/index.ts)_
## `eas deploy:alias`
@@ -1038,7 +1041,7 @@ ALIASES
$ eas deploy:promote
```
_See code: [packages/eas-cli/src/commands/deploy/alias/index.ts](https://github.com/expo/eas-cli/blob/v16.25.0/packages/eas-cli/src/commands/deploy/alias/index.ts)_
_See code: [packages/eas-cli/src/commands/deploy/alias/index.ts](https://github.com/expo/eas-cli/blob/v16.28.0/packages/eas-cli/src/commands/deploy/alias/index.ts)_
## `eas deploy:alias:delete [ALIAS_NAME]`
@@ -1059,7 +1062,7 @@ ALIASES
$ eas worker:alias:delete
```
_See code: [packages/eas-cli/src/commands/deploy/alias/delete.ts](https://github.com/expo/eas-cli/blob/v16.25.0/packages/eas-cli/src/commands/deploy/alias/delete.ts)_
_See code: [packages/eas-cli/src/commands/deploy/alias/delete.ts](https://github.com/expo/eas-cli/blob/v16.28.0/packages/eas-cli/src/commands/deploy/alias/delete.ts)_
## `eas deploy:delete [DEPLOYMENT_ID]`
@@ -1080,7 +1083,7 @@ ALIASES
$ eas worker:delete
```
_See code: [packages/eas-cli/src/commands/deploy/delete.ts](https://github.com/expo/eas-cli/blob/v16.25.0/packages/eas-cli/src/commands/deploy/delete.ts)_
_See code: [packages/eas-cli/src/commands/deploy/delete.ts](https://github.com/expo/eas-cli/blob/v16.28.0/packages/eas-cli/src/commands/deploy/delete.ts)_
## `eas deploy:promote`
@@ -1117,7 +1120,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.25.0/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.28.0/packages/eas-cli/src/commands/device/create.ts)_
## `eas device:delete`
@@ -1137,7 +1140,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.25.0/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.28.0/packages/eas-cli/src/commands/device/delete.ts)_
## `eas device:list`
@@ -1158,7 +1161,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.25.0/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.28.0/packages/eas-cli/src/commands/device/list.ts)_
## `eas device:rename`
@@ -1179,7 +1182,7 @@ DESCRIPTION
rename a registered device
```
_See code: [packages/eas-cli/src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/device/rename.ts)_
## `eas device:view [UDID]`
@@ -1193,7 +1196,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.25.0/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.28.0/packages/eas-cli/src/commands/device/view.ts)_
## `eas diagnostics`
@@ -1207,7 +1210,7 @@ DESCRIPTION
display environment info
```
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v16.25.0/packages/eas-cli/src/commands/diagnostics.ts)_
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v16.28.0/packages/eas-cli/src/commands/diagnostics.ts)_
## `eas env:create [ENVIRONMENT]`
@@ -1237,7 +1240,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.25.0/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.28.0/packages/eas-cli/src/commands/env/create.ts)_
## `eas env:delete [ENVIRONMENT]`
@@ -1262,7 +1265,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.25.0/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.28.0/packages/eas-cli/src/commands/env/delete.ts)_
## `eas env:exec ENVIRONMENT BASH_COMMAND`
@@ -1284,7 +1287,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.25.0/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.28.0/packages/eas-cli/src/commands/env/exec.ts)_
## `eas env:get [ENVIRONMENT]`
@@ -1309,7 +1312,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.25.0/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.28.0/packages/eas-cli/src/commands/env/get.ts)_
## `eas env:list [ENVIRONMENT]`
@@ -1335,7 +1338,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.25.0/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.28.0/packages/eas-cli/src/commands/env/list.ts)_
## `eas env:pull [ENVIRONMENT]`
@@ -1357,7 +1360,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.25.0/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.28.0/packages/eas-cli/src/commands/env/pull.ts)_
## `eas env:push [ENVIRONMENT]`
@@ -1379,7 +1382,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.25.0/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.28.0/packages/eas-cli/src/commands/env/push.ts)_
## `eas env:update [ENVIRONMENT]`
@@ -1411,7 +1414,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.25.0/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.28.0/packages/eas-cli/src/commands/env/update.ts)_
## `eas fingerprint:compare [HASH1] [HASH2]`
@@ -1455,7 +1458,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.25.0/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.28.0/packages/eas-cli/src/commands/fingerprint/compare.ts)_
## `eas fingerprint:generate`
@@ -1485,7 +1488,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.25.0/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.28.0/packages/eas-cli/src/commands/fingerprint/generate.ts)_
## `eas help [COMMAND]`
@@ -1593,7 +1596,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.25.0/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.28.0/packages/eas-cli/src/commands/metadata/lint.ts)_
## `eas metadata:pull`
@@ -1610,7 +1613,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.25.0/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.28.0/packages/eas-cli/src/commands/metadata/pull.ts)_
## `eas metadata:push`
@@ -1627,7 +1630,28 @@ 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.25.0/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.28.0/packages/eas-cli/src/commands/metadata/push.ts)_
## `eas new [PATH]`
Create a new project configured with Expo Application Services (EAS)
```
USAGE
$ eas new [PATH] [-p bun|npm|pnpm|yarn]
ARGUMENTS
PATH Path to create the project (defaults to current directory)
FLAGS
-p, --package-manager=(bun|npm|pnpm|yarn) [default: npm] Package manager to use for installing dependencies
DESCRIPTION
Create a new project configured with Expo Application Services (EAS)
ALIASES
$ eas new
```
## `eas onboarding [TARGET_PROJECT_DIRECTORY]`
@@ -1657,7 +1681,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.25.0/packages/eas-cli/src/commands/open.ts)_
_See code: [packages/eas-cli/src/commands/open.ts](https://github.com/expo/eas-cli/blob/v16.28.0/packages/eas-cli/src/commands/open.ts)_
## `eas project:info`
@@ -1671,7 +1695,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.25.0/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.28.0/packages/eas-cli/src/commands/project/info.ts)_
## `eas project:init`
@@ -1694,7 +1718,30 @@ ALIASES
$ eas init
```
_See code: [packages/eas-cli/src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/project/init.ts)_
## `eas project:new [PATH]`
Create a new project configured with Expo Application Services (EAS)
```
USAGE
$ eas project:new [PATH] [-p bun|npm|pnpm|yarn]
ARGUMENTS
PATH Path to create the project (defaults to current directory)
FLAGS
-p, --package-manager=(bun|npm|pnpm|yarn) [default: npm] Package manager to use for installing dependencies
DESCRIPTION
Create a new project configured with Expo Application Services (EAS)
ALIASES
$ eas new
```
_See code: [packages/eas-cli/src/commands/project/new.ts](https://github.com/expo/eas-cli/blob/v16.28.0/packages/eas-cli/src/commands/project/new.ts)_
## `eas project:onboarding [TARGET_PROJECT_DIRECTORY]`
@@ -1712,7 +1759,7 @@ ALIASES
$ eas onboarding
```
_See code: [packages/eas-cli/src/commands/project/onboarding.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/project/onboarding.ts)_
## `eas submit`
@@ -1747,7 +1794,7 @@ ALIASES
$ eas build:submit
```
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v16.25.0/packages/eas-cli/src/commands/submit.ts)_
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v16.28.0/packages/eas-cli/src/commands/submit.ts)_
## `eas update`
@@ -1787,7 +1834,7 @@ DESCRIPTION
publish an update group
```
_See code: [packages/eas-cli/src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/update/index.ts)_
## `eas update:configure`
@@ -1807,7 +1854,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.25.0/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.28.0/packages/eas-cli/src/commands/update/configure.ts)_
## `eas update:delete GROUPID`
@@ -1828,7 +1875,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.25.0/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.28.0/packages/eas-cli/src/commands/update/delete.ts)_
## `eas update:edit [GROUPID]`
@@ -1852,7 +1899,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.25.0/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.28.0/packages/eas-cli/src/commands/update/edit.ts)_
## `eas update:list`
@@ -1874,7 +1921,7 @@ DESCRIPTION
view the recent updates
```
_See code: [packages/eas-cli/src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/update/list.ts)_
## `eas update:republish`
@@ -1910,7 +1957,7 @@ 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.25.0/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.28.0/packages/eas-cli/src/commands/update/republish.ts)_
## `eas update:revert-update-rollout`
@@ -1937,7 +1984,7 @@ 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.25.0/packages/eas-cli/src/commands/update/revert-update-rollout.ts)_
_See code: [packages/eas-cli/src/commands/update/revert-update-rollout.ts](https://github.com/expo/eas-cli/blob/v16.28.0/packages/eas-cli/src/commands/update/revert-update-rollout.ts)_
## `eas update:roll-back-to-embedded`
@@ -1965,7 +2012,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.25.0/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.28.0/packages/eas-cli/src/commands/update/roll-back-to-embedded.ts)_
## `eas update:rollback`
@@ -1986,7 +2033,7 @@ DESCRIPTION
instead execute "eas update:republish" or "eas update:roll-back-to-embedded".
```
_See code: [packages/eas-cli/src/commands/update/rollback.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/update/rollback.ts)_
## `eas update:view GROUPID`
@@ -2006,7 +2053,7 @@ DESCRIPTION
update group details
```
_See code: [packages/eas-cli/src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/update/view.ts)_
## `eas upload`
@@ -2027,7 +2074,7 @@ 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.25.0/packages/eas-cli/src/commands/upload.ts)_
_See code: [packages/eas-cli/src/commands/upload.ts](https://github.com/expo/eas-cli/blob/v16.28.0/packages/eas-cli/src/commands/upload.ts)_
## `eas webhook:create`
@@ -2048,7 +2095,7 @@ DESCRIPTION
create a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/webhook/create.ts)_
## `eas webhook:delete [ID]`
@@ -2068,7 +2115,7 @@ DESCRIPTION
delete a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/webhook/delete.ts)_
## `eas webhook:list`
@@ -2086,7 +2133,7 @@ DESCRIPTION
list webhooks
```
_See code: [packages/eas-cli/src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/webhook/list.ts)_
## `eas webhook:update`
@@ -2108,7 +2155,7 @@ DESCRIPTION
update a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/webhook/update.ts)_
## `eas webhook:view ID`
@@ -2125,7 +2172,7 @@ DESCRIPTION
view a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/webhook/view.ts)_
## `eas whoami`
@@ -2245,7 +2292,7 @@ DESCRIPTION
to cancel.
```
_See code: [packages/eas-cli/src/commands/workflow/cancel.ts](https://github.com/expo/eas-cli/blob/v16.25.0/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.28.0/packages/eas-cli/src/commands/workflow/cancel.ts)_
## `eas workflow:create [NAME]`
@@ -2265,7 +2312,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.25.0/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.28.0/packages/eas-cli/src/commands/workflow/create.ts)_
## `eas workflow:logs [ID]`
@@ -2289,7 +2336,7 @@ DESCRIPTION
If no ID is passed in, you will be prompted to select from recent workflow runs for the current project.
```
_See code: [packages/eas-cli/src/commands/workflow/logs.ts](https://github.com/expo/eas-cli/blob/v16.25.0/packages/eas-cli/src/commands/workflow/logs.ts)_
_See code: [packages/eas-cli/src/commands/workflow/logs.ts](https://github.com/expo/eas-cli/blob/v16.28.0/packages/eas-cli/src/commands/workflow/logs.ts)_
## `eas workflow:run [FILE]`
@@ -2329,7 +2376,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.25.0/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.28.0/packages/eas-cli/src/commands/workflow/run.ts)_
## `eas workflow:runs`
@@ -2354,7 +2401,35 @@ 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.25.0/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.28.0/packages/eas-cli/src/commands/workflow/runs.ts)_
## `eas workflow:status [WORKFLOW_RUN_ID]`
show the status of an existing workflow run. If no run ID is provided, you will be prompted to select from recent workflow runs for the current project.
```
USAGE
$ eas workflow:status [WORKFLOW_RUN_ID] [--non-interactive] [--wait] [--json]
ARGUMENTS
WORKFLOW_RUN_ID A workflow run ID.
FLAGS
--json Enable JSON output, non-JSON messages will be printed to stderr.
--non-interactive Run the command in non-interactive mode.
--[no-]wait Wait for workflow run to complete. Defaults to false.
DESCRIPTION
show the status of an existing workflow run. If no run ID is provided, you will be prompted to select from recent
workflow runs for the current project.
FLAG DESCRIPTIONS
--[no-]wait Wait for workflow run to complete. Defaults to false.
Exit codes: 0 = success, 11 = failure, 12 = canceled, 13 = wait aborted.
```
_See code: [packages/eas-cli/src/commands/workflow/status.ts](https://github.com/expo/eas-cli/blob/v16.28.0/packages/eas-cli/src/commands/workflow/status.ts)_
## `eas workflow:validate PATH`
@@ -2374,7 +2449,7 @@ 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.25.0/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.28.0/packages/eas-cli/src/commands/workflow/validate.ts)_
## `eas workflow:view [ID]`
@@ -2396,5 +2471,5 @@ DESCRIPTION
workflow runs for the current project.
```
_See code: [packages/eas-cli/src/commands/workflow/view.ts](https://github.com/expo/eas-cli/blob/v16.25.0/packages/eas-cli/src/commands/workflow/view.ts)_
_See code: [packages/eas-cli/src/commands/workflow/view.ts](https://github.com/expo/eas-cli/blob/v16.28.0/packages/eas-cli/src/commands/workflow/view.ts)_
<!-- commandsstop -->
+2509 -3
View File
File diff suppressed because it is too large. Load diff
+4 -3
View File
@@ -1,7 +1,7 @@
{
"name": "eas-cli",
"description": "EAS command line tool",
"version": "16.25.0",
"version": "16.28.0",
"author": "Expo <[email protected]>",
"bin": {
"eas": "./bin/run"
@@ -226,11 +226,12 @@
"prepack": "yarn rebuild && node ./scripts/prepack.js",
"rebuild": "rimraf build && yarn build",
"pretarball-ci": "./scripts/pretarball-ci.sh",
"build": "tsc --project tsconfig.build.json && yarn copy-new-templates",
"build": "yarn typecheck-for-build && yarn copy-new-templates",
"build-allow-unused": "tsc --project tsconfig.allowUnused.json",
"watch": "yarn build --watch --preserveWatchOutput",
"watch": "yarn typecheck-for-build --watch --preserveWatchOutput",
"watch-allow-unused": "yarn build-allow-unused --watch --preserveWatchOutput",
"typecheck": "tsc",
"typecheck-for-build": "tsc --project tsconfig.build.json",
"test": "jest",
"version": "yarn oclif readme && node scripts/patch-readme && git add README.md",
"generate-graphql-code": "graphql-codegen --config graphql-codegen.yml",
+39
View File
@@ -0,0 +1,39 @@
import gql from 'graphql-tag';
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
import { withErrorHandlingAsync } from '../graphql/client';
import {
BackgroundJobReceiptDataFragment,
ScheduleBranchDeletionMutation,
ScheduleBranchDeletionMutationVariables,
} from '../graphql/generated';
import { BackgroundJobReceiptNode } from '../graphql/types/BackgroundJobReceipt';
export async function scheduleBranchDeletionAsync(
graphqlClient: ExpoGraphqlClient,
{
branchId,
}: {
branchId: string;
}
): Promise<BackgroundJobReceiptDataFragment> {
const result = await withErrorHandlingAsync(
graphqlClient
.mutation<ScheduleBranchDeletionMutation, ScheduleBranchDeletionMutationVariables>(
gql`
mutation ScheduleBranchDeletion($branchId: ID!) {
updateBranch {
scheduleUpdateBranchDeletion(branchId: $branchId) {
id
...BackgroundJobReceiptData
}
}
}
${BackgroundJobReceiptNode}
`,
{ branchId }
)
.toPromise()
);
return result.updateBranch.scheduleUpdateBranchDeletion;
}
+1
View File
@@ -33,6 +33,7 @@ export interface IosBuildContext {
}
export interface BuildContext<T extends Platform> {
accountId: string;
accountName: string;
easJsonCliConfig: EasJson['cli'];
buildProfile: BuildProfile<T>;
@@ -125,6 +125,7 @@ export async function createBuildContextAsync<T extends Platform>({
);
const commonContext: CommonContext<T> = {
accountId,
accountName: account.name,
buildProfile,
buildProfileName,
@@ -78,10 +78,12 @@ import { downloadAndMaybeExtractAppAsync } from '../utils/download';
import { truthy } from '../utils/expodash/filter';
import { printJsonOnlyOutput } from '../utils/json';
import { ProfileData, getProfilesAsync } from '../utils/profiles';
import { maybeWarnAboutUsageOveragesAsync } from '../utils/usage/checkForOverages';
import { Client } from '../vcs/vcs';
let metroConfigValidated = false;
let sdkVersionChecked = false;
let hasWarnedAboutUsageOverages = false;
export interface BuildFlags {
requestedPlatform: RequestedPlatform;
@@ -409,6 +411,15 @@ async function prepareAndStartBuildAsync({
env,
});
if (!hasWarnedAboutUsageOverages && !flags.localBuildOptions.localBuildMode) {
hasWarnedAboutUsageOverages = true;
Log.newLine();
await maybeWarnAboutUsageOveragesAsync({ graphqlClient, accountId: buildCtx.accountId });
if (!moreBuilds) {
Log.newLine();
}
}
if (moreBuilds) {
Log.newLine();
const appPlatform = toAppPlatform(buildProfile.platform);
@@ -158,10 +158,6 @@ describe('configs', () => {
const result = getAccountChoices(jester);
expect(result).toEqual([
{
title: 'jester (personal account)',
value: { name: 'jester' },
},
{
title: 'other',
value: { name: 'other' },
@@ -169,6 +165,10 @@ describe('configs', () => {
description:
'You do not have the required permissions to create projects on this account.',
},
{
title: 'jester',
value: { name: 'jester' },
},
]);
});
});
@@ -117,15 +117,18 @@ export async function promptForProjectAccountAsync(actor: Actor): Promise<string
export function getAccountChoices(actor: Actor, permissionsMap?: Map<string, boolean>): Choice[] {
const permissions = permissionsMap ?? getAccountPermissionsMap(actor);
const sortedAccounts = [...actor.accounts].sort((a, _b) =>
actor.__typename === 'User' ? (a.name === actor.username ? -1 : 1) : 0
);
const sortedAccounts = [...actor.accounts].sort((a, _b) => (a.ownerUserActor ? 1 : -1));
return sortedAccounts.map(account => {
const isPersonalAccount = actor.__typename === 'User' && account.name === actor.username;
const isPersonalAccount = !!account.ownerUserActor && account.ownerUserActor.id === actor.id;
const isTeamAccount = !!account.ownerUserActor && account.ownerUserActor.id !== actor.id;
const accountDisplayName = isPersonalAccount
? `${account.name} (personal account)`
: account.name;
? `${account.name} (Limited - Personal Account)`
: isTeamAccount
? `${account.name} (Limited - Team Account)`
: account.name;
const disabled = !permissions.get(account.name);
return {
@@ -21,7 +21,7 @@ This project is configured to use [EAS Workflows](https://docs.expo.dev/eas/work
### Previews
Run `npm run preview` to [publish a preview update](https://docs.expo.dev/eas/workflows/examples/publish-preview-update/) of your project, which can be viewed in Expo Go or in a development build.
Run `npm run draft` to [publish a preview update](https://docs.expo.dev/eas/workflows/examples/publish-preview-update/) of your project, which can be viewed in Expo Go or in a development build.
### Development Builds
@@ -1,3 +1,4 @@
import chalk from 'chalk';
import * as fs from 'node:fs';
import { fetchRawLogsForBuildJobAsync, fetchRawLogsForCustomJobAsync } from './fetchLogs';
@@ -11,14 +12,18 @@ import {
import {
WorkflowJobStatus,
WorkflowJobType,
WorkflowRunByIdQuery,
WorkflowRunByIdWithJobsQuery,
WorkflowRunFragment,
WorkflowRunStatus,
WorkflowRunTriggerEventType,
} from '../../graphql/generated';
import { WorkflowRunQuery } from '../../graphql/queries/WorkflowRunQuery';
import Log from '../../log';
import { ora } from '../../ora';
import { Choice } from '../../prompts';
import formatFields from '../../utils/formatFields';
import { sleepAsync } from '../../utils/promise';
import { ExpoGraphqlClient } from '../context/contextUtils/createGraphqlClient';
export function computeTriggerInfoForWorkflowRun(run: WorkflowRunFragment): {
@@ -218,10 +223,12 @@ export async function infoForActiveWorkflowRunAsync(
export async function infoForFailedWorkflowRunAsync(
graphqlClient: ExpoGraphqlClient,
workflowRun: WorkflowRunByIdWithJobsQuery['workflowRuns']['byId']
workflowRun: WorkflowRunByIdWithJobsQuery['workflowRuns']['byId'],
maxLogLines: number = -1 // -1 means no limit
): Promise<string> {
const statusLines = [];
const statusValues = [];
const logLinesToKeep = maxLogLines === -1 ? Infinity : maxLogLines;
for (const job of workflowRun.jobs) {
if (job.status !== WorkflowJobStatus.Failure) {
continue;
@@ -233,7 +240,7 @@ export async function infoForFailedWorkflowRunAsync(
if (steps.length > 0) {
const failedStep = steps.find(step => step.status === 'fail');
if (failedStep) {
const logs = failedStep.logLines?.map(line => line.msg) ?? [];
const logs = failedStep.logLines?.map(line => line.msg).slice(-logLinesToKeep) ?? [];
statusValues.push({ label: ' Failed step', value: failedStep.name });
statusValues.push({
label: ' Logs for failed step',
@@ -283,3 +290,84 @@ export async function maybeReadStdinAsync(): Promise<string | null> {
});
});
}
export async function showWorkflowStatusAsync(
graphqlClient: ExpoGraphqlClient,
{
workflowRunId,
spinnerUsesStdErr,
waitForCompletion = true,
}: { workflowRunId: string; spinnerUsesStdErr: boolean; waitForCompletion?: boolean }
): Promise<WorkflowRunByIdQuery['workflowRuns']['byId']> {
Log.log('Waiting for workflow run to complete. You can press Ctrl+C to exit.');
const spinner = ora({
stream: spinnerUsesStdErr ? process.stderr : process.stdout,
text: '',
}).start();
spinner.prefixText = chalk`{bold.yellow Workflow run is waiting to start:}`;
let failedFetchesCount = 0;
while (true) {
try {
const workflowRun = await WorkflowRunQuery.withJobsByIdAsync(graphqlClient, workflowRunId, {
useCache: false,
});
failedFetchesCount = 0;
switch (workflowRun.status) {
case WorkflowRunStatus.New:
break;
case WorkflowRunStatus.InProgress: {
spinner.prefixText = chalk`{bold.green Workflow run is in progress:}`;
spinner.text = await infoForActiveWorkflowRunAsync(graphqlClient, workflowRun, 5);
break;
}
case WorkflowRunStatus.ActionRequired:
spinner.prefixText = chalk`{bold.yellow Workflow run is waiting for action:}`;
break;
case WorkflowRunStatus.Canceled:
spinner.prefixText = chalk`{bold.yellow Workflow has been canceled.}`;
spinner.stopAndPersist();
return workflowRun;
case WorkflowRunStatus.Failure: {
spinner.prefixText = chalk`{bold.red Workflow has failed.}`;
const failedInfo = await infoForFailedWorkflowRunAsync(graphqlClient, workflowRun, 30);
spinner.fail(failedInfo);
return workflowRun;
}
case WorkflowRunStatus.Success:
spinner.prefixText = chalk`{bold.green Workflow has completed successfully.}`;
spinner.text = '';
spinner.succeed('');
return workflowRun;
}
if (!waitForCompletion) {
if (spinner.isSpinning) {
spinner.stopAndPersist();
}
return workflowRun;
}
} catch {
spinner.text = '⚠ Failed to fetch the workflow run status. Check your network connection.';
failedFetchesCount += 1;
if (failedFetchesCount > 6) {
spinner.fail('Failed to fetch the workflow run status 6 times in a row. Aborting wait.');
process.exit(workflowRunExitCodes.WAIT_ABORTED);
}
}
await sleepAsync(10 /* seconds */ * 1000 /* milliseconds */);
}
}
export const workflowRunExitCodes = {
WORKFLOW_FAILED: 11,
WORKFLOW_CANCELED: 12,
WAIT_ABORTED: 13,
};
+7 -36
View File
@@ -1,23 +1,19 @@
import chalk from 'chalk';
import gql from 'graphql-tag';
import { scheduleBranchDeletionAsync } from '../../branch/delete';
import { selectBranchOnAppAsync } from '../../branch/queries';
import EasCommand from '../../commandUtils/EasCommand';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
import { getPaginatedQueryOptions } from '../../commandUtils/pagination';
import { withErrorHandlingAsync } from '../../graphql/client';
import {
DeleteUpdateBranchMutation,
DeleteUpdateBranchMutationVariables,
DeleteUpdateBranchResult,
GetBranchInfoQuery,
GetBranchInfoQueryVariables,
} from '../../graphql/generated';
import { GetBranchInfoQuery, GetBranchInfoQueryVariables } from '../../graphql/generated';
import Log from '../../log';
import { getDisplayNameForProjectIdAsync } from '../../project/projectUtils';
import { toggleConfirmAsync } from '../../prompts';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
import { pollForBackgroundJobReceiptAsync } from '../../utils/pollForBackgroundJobReceiptAsync';
async function getBranchInfoAsync(
graphqlClient: ExpoGraphqlClient,
@@ -50,31 +46,6 @@ async function getBranchInfoAsync(
return data;
}
async function deleteBranchOnAppAsync(
graphqlClient: ExpoGraphqlClient,
{ branchId }: DeleteUpdateBranchMutationVariables
): Promise<DeleteUpdateBranchResult> {
const data = await withErrorHandlingAsync(
graphqlClient
.mutation<DeleteUpdateBranchMutation, DeleteUpdateBranchMutationVariables>(
gql`
mutation DeleteUpdateBranch($branchId: ID!) {
updateBranch {
deleteUpdateBranch(branchId: $branchId) {
id
}
}
}
`,
{
branchId,
}
)
.toPromise()
);
return data.updateBranch.deleteUpdateBranch;
}
export default class BranchDelete extends EasCommand {
static override description = 'delete a branch';
@@ -146,12 +117,12 @@ export default class BranchDelete extends EasCommand {
}
}
const deletionResult = await deleteBranchOnAppAsync(graphqlClient, {
branchId,
});
const receipt = await scheduleBranchDeletionAsync(graphqlClient, { branchId });
const successfulReceipt = await pollForBackgroundJobReceiptAsync(graphqlClient, receipt);
Log.debug('Deletion result', { successfulReceipt });
if (jsonFlag) {
printJsonOnlyOutput(deletionResult);
printJsonOnlyOutput({ id: branchId });
} else {
Log.withTick(
`️Deleted branch "${branchName}" and all of its updates on project ${chalk.bold(
@@ -14,13 +14,11 @@ import { EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
import { StatuspageServiceName } from '../../graphql/generated';
import Log, { link } from '../../log';
import { RequestedPlatform, selectRequestedPlatformAsync } from '../../platform';
import { getOwnerAccountForProjectIdAsync } from '../../project/projectUtils';
import { selectAsync } from '../../prompts';
import uniq from '../../utils/expodash/uniq';
import { enableJsonOutput } from '../../utils/json';
import { ProfileData } from '../../utils/profiles';
import { maybeWarnAboutEasOutagesAsync } from '../../utils/statuspageService';
import { maybeWarnAboutUsageOveragesAsync } from '../../utils/usage/checkForOverages';
interface RawBuildFlags {
platform?: string;
@@ -163,13 +161,6 @@ export default class Build extends EasCommand {
? [StatuspageServiceName.EasBuild, StatuspageServiceName.EasSubmit]
: [StatuspageServiceName.EasBuild]
);
const { projectId } = await getDynamicPrivateProjectConfigAsync();
const account = await getOwnerAccountForProjectIdAsync(graphqlClient, projectId);
await maybeWarnAboutUsageOveragesAsync({
graphqlClient,
accountId: account.id,
});
}
const flagsWithPlatform = await this.ensurePlatformSelectedAsync(flags);
@@ -44,8 +44,6 @@ export default class WorkerAliasDelete extends EasCommand {
enableJsonOutput();
}
Log.warn('EAS Hosting is still in preview and subject to changes.');
const {
getDynamicPrivateProjectConfigAsync,
loggedIn: { graphqlClient },
@@ -73,8 +73,6 @@ export default class WorkerAlias extends EasCommand {
enableJsonOutput();
}
Log.warn('EAS Hosting is still in preview and subject to changes.');
const {
getDynamicPrivateProjectConfigAsync,
loggedIn: { graphqlClient },
@@ -45,8 +45,6 @@ export default class WorkerDelete extends EasCommand {
enableJsonOutput();
}
Log.warn('EAS Hosting is still in preview and subject to changes.');
const {
getDynamicPrivateProjectConfigAsync,
loggedIn: { graphqlClient },
@@ -120,8 +120,6 @@ export default class WorkerDeploy extends EasCommand {
enableJsonOutput();
}
Log.warn('EAS Hosting is still in preview and subject to changes.');
const {
getDynamicPrivateProjectConfigAsync,
loggedIn: { graphqlClient },
@@ -1,5 +1,6 @@
import { Config } from '@oclif/core';
import chalk from 'chalk';
import * as fs from 'fs-extra';
import { getMockAppFragment } from '../../../__tests__/commands/utils';
import { DefaultEnvironment } from '../../../build/utils/environment';
@@ -26,6 +27,7 @@ jest.mock('../../../prompts');
jest.mock('../../../utils/prompts');
jest.mock('../../../graphql/queries/AppQuery');
jest.mock('../../../log');
jest.mock('fs-extra');
describe(EnvUpdate, () => {
const projectId = 'test-project-id';
@@ -251,4 +253,251 @@ describe(EnvUpdate, () => {
filterNames: ['TEST_VAR_1'],
});
});
it('processes file type variable in non-interactive mode with --type file and --value', async () => {
const testFilePath = '/path/to/test-file.json';
const testFileBase64 = 'dGVzdCBmaWxlIGNvbnRlbnQ=';
const testFileName = 'test-file.json';
const mockVariable = {
id: variableId,
name: 'TEST_VARIABLE',
scope: EnvironmentVariableScope.Project,
environments: [DefaultEnvironment.Development],
type: EnvironmentSecretType.String,
};
const mockUpdatedVariable = {
...mockVariable,
type: EnvironmentSecretType.FileBase64,
};
(EnvironmentVariablesQuery.byAppIdAsync as jest.Mock).mockResolvedValue([mockVariable]);
(EnvironmentVariableMutation.updateAsync as jest.Mock).mockResolvedValue(mockUpdatedVariable);
// Mock fs.pathExists to return true
jest.mocked(fs.pathExists).mockImplementation(() => Promise.resolve(true));
// Mock fs.readFile to return base64 encoded content
jest.mocked(fs.readFile).mockImplementation(() => Promise.resolve(testFileBase64));
const command = new EnvUpdate(
[
'--variable-name',
'TEST_VARIABLE',
'--variable-environment',
'development',
'--non-interactive',
'--type',
'file',
'--value',
testFilePath,
'--environment',
'production',
],
mockConfig
);
// @ts-expect-error
jest.spyOn(command, 'getContextAsync').mockReturnValue(mockContext);
await command.runAsync();
// Verify file was checked for existence
expect(fs.pathExists).toHaveBeenCalledWith(testFilePath);
// Verify file was read as base64
expect(fs.readFile).toHaveBeenCalledWith(testFilePath, 'base64');
// Verify update was called with FileBase64 type and base64-encoded value
expect(EnvironmentVariableMutation.updateAsync).toHaveBeenCalledWith(graphqlClient, {
id: variableId,
value: testFileBase64,
environments: [DefaultEnvironment.Production],
type: EnvironmentSecretType.FileBase64,
fileName: testFileName,
});
});
it('throws error when updating FILE type variable with value that is not a valid file path', async () => {
const plainStringValue = 'some-new-value';
const mockVariable = {
id: variableId,
name: 'TEST_VARIABLE',
scope: EnvironmentVariableScope.Project,
environments: [DefaultEnvironment.Development],
type: EnvironmentSecretType.FileBase64,
};
(EnvironmentVariablesQuery.byAppIdAsync as jest.Mock).mockResolvedValue([mockVariable]);
// Mock fs.pathExists to return false (file doesn't exist)
jest.mocked(fs.pathExists).mockImplementation(() => Promise.resolve(false));
const command = new EnvUpdate(
[
'--variable-name',
'TEST_VARIABLE',
'--variable-environment',
'development',
'--non-interactive',
'--value',
plainStringValue,
'--environment',
'production',
// Note: --type is NOT specified
],
mockConfig
);
// @ts-expect-error
jest.spyOn(command, 'getContextAsync').mockReturnValue(mockContext);
// Should throw error when FILE type variable is updated with non-file value
await expect(command.runAsync()).rejects.toThrow(
`Variable "TEST_VARIABLE" is a file type, but "${plainStringValue}" does not exist as a file. If you want to convert it to a string, pass --type string.`
);
});
it('throws error when --type file is explicitly specified but file does not exist', async () => {
const nonExistentFilePath = '/path/to/nonexistent-file.json';
const mockVariable = {
id: variableId,
name: 'TEST_VARIABLE',
scope: EnvironmentVariableScope.Project,
environments: [DefaultEnvironment.Development],
type: EnvironmentSecretType.String,
};
(EnvironmentVariablesQuery.byAppIdAsync as jest.Mock).mockResolvedValue([mockVariable]);
// Mock fs.pathExists to return false (file doesn't exist)
jest.mocked(fs.pathExists).mockImplementation(() => Promise.resolve(false));
const command = new EnvUpdate(
[
'--variable-name',
'TEST_VARIABLE',
'--variable-environment',
'development',
'--non-interactive',
'--type',
'file',
'--value',
nonExistentFilePath,
'--environment',
'production',
],
mockConfig
);
// @ts-expect-error
jest.spyOn(command, 'getContextAsync').mockReturnValue(mockContext);
// Should throw error when --type file is explicitly specified
await expect(command.runAsync()).rejects.toThrow(
`File "${nonExistentFilePath}" does not exist`
);
});
it('preserves existing STRING type when updating value without --type flag', async () => {
const stringValue = 'my-best-file.json';
const mockVariable = {
id: variableId,
name: 'MY_VAR',
scope: EnvironmentVariableScope.Project,
environments: [DefaultEnvironment.Development],
type: EnvironmentSecretType.String,
value: 'old-value',
visibility: EnvironmentVariableVisibility.Public,
};
const mockUpdatedVariable = {
...mockVariable,
value: stringValue,
};
(EnvironmentVariablesQuery.byAppIdAsync as jest.Mock).mockResolvedValue([mockVariable]);
(EnvironmentVariableMutation.updateAsync as jest.Mock).mockResolvedValue(mockUpdatedVariable);
const command = new EnvUpdate(
[
'--variable-name',
'MY_VAR',
'--variable-environment',
'development',
'--non-interactive',
'--value',
stringValue,
// Note: --type is NOT specified
],
mockConfig
);
// @ts-expect-error
jest.spyOn(command, 'getContextAsync').mockReturnValue(mockContext);
await command.runAsync();
// Verify update was called with preserved STRING type
expect(EnvironmentVariableMutation.updateAsync).toHaveBeenCalledWith(graphqlClient, {
id: variableId,
value: stringValue,
type: EnvironmentSecretType.String,
});
});
it('preserves existing FILE type when updating value without --type flag', async () => {
const testFilePath = '/path/to/test-file.json';
const testFileBase64 = 'dGVzdCBmaWxlIGNvbnRlbnQ=';
const testFileName = 'test-file.json';
const mockVariable = {
id: variableId,
name: 'MY_FILE_VAR',
scope: EnvironmentVariableScope.Project,
environments: [DefaultEnvironment.Development],
type: EnvironmentSecretType.FileBase64,
value: 'old-base64-value',
visibility: EnvironmentVariableVisibility.Public,
};
const mockUpdatedVariable = {
...mockVariable,
value: testFileBase64,
};
(EnvironmentVariablesQuery.byAppIdAsync as jest.Mock).mockResolvedValue([mockVariable]);
(EnvironmentVariableMutation.updateAsync as jest.Mock).mockResolvedValue(mockUpdatedVariable);
// Mock fs.pathExists to return true
jest.mocked(fs.pathExists).mockImplementation(() => Promise.resolve(true));
// Mock fs.readFile to return base64 encoded content
jest.mocked(fs.readFile).mockImplementation(() => Promise.resolve(testFileBase64));
const command = new EnvUpdate(
[
'--variable-name',
'MY_FILE_VAR',
'--variable-environment',
'development',
'--non-interactive',
'--value',
testFilePath,
// Note: --type is NOT specified
],
mockConfig
);
// @ts-expect-error
jest.spyOn(command, 'getContextAsync').mockReturnValue(mockContext);
await command.runAsync();
// Verify file was checked for existence
expect(fs.pathExists).toHaveBeenCalledWith(testFilePath);
// Verify file was read as base64
expect(fs.readFile).toHaveBeenCalledWith(testFilePath, 'base64');
// Verify update was called with preserved FILE type
expect(EnvironmentVariableMutation.updateAsync).toHaveBeenCalledWith(graphqlClient, {
id: variableId,
value: testFileBase64,
type: EnvironmentSecretType.FileBase64,
fileName: testFileName,
});
});
});
+20 -12
View File
@@ -299,18 +299,6 @@ export default class EnvUpdate extends EasCommand {
}
}
let environmentFilePath: string | undefined;
if ((newType ?? selectedVariable.type) === EnvironmentSecretType.FileBase64 && value) {
environmentFilePath = path.resolve(value);
if (!(await fs.pathExists(environmentFilePath))) {
throw new Error(`File "${value}" does not exist`);
}
fileName = path.basename(environmentFilePath);
}
value = environmentFilePath ? await fs.readFile(environmentFilePath, 'base64') : value;
if (!environments || environments.length === 0) {
environments = await promptVariableEnvironmentAsync({
nonInteractive,
@@ -342,6 +330,26 @@ export default class EnvUpdate extends EasCommand {
}
}
// If value is provided but type is not explicitly set, preserve the existing type
if (value && !newType) {
newType = selectedVariable.type;
}
if (newType === EnvironmentSecretType.FileBase64 && value) {
const environmentFilePath = path.resolve(value);
if (!(await fs.pathExists(environmentFilePath))) {
if (type === 'file') {
throw new Error(`File "${value}" does not exist`);
} else {
throw new Error(
`Variable "${selectedVariable.name}" is a file type, but "${value}" does not exist as a file. If you want to convert it to a string, pass --type string.`
);
}
}
fileName = path.basename(environmentFilePath);
value = await fs.readFile(environmentFilePath, 'base64');
}
if (visibility) {
newVisibility = parseVisibility(visibility);
}
+6 -6
View File
@@ -149,8 +149,6 @@ export default class New extends EasCommand {
}),
};
static override hidden = true;
static override contextDefinition = {
...this.ContextOptions.LoggedIn,
};
@@ -197,17 +195,19 @@ export default class New extends EasCommand {
Log.log('🎉 We finished creating your new project.');
Log.newLine();
Log.log('Next steps:');
Log.withInfo(`Run \`cd ${printDirectory(projectDirectory)}\` to navigate to your project.`);
Log.withInfo(
`Run \`${packageManager} run draft\` to create a preview on EAS. ${learnMore(
`Run ${chalk.bold(`cd ${printDirectory(projectDirectory)}`)} to navigate to your project.`
);
Log.withInfo(
`Run ${chalk.bold(`${packageManager} run draft`)} to create a preview on EAS. ${learnMore(
'https://docs.expo.dev/eas/workflows/examples/publish-preview-update/'
)}`
);
Log.withInfo(
`Run \`${packageManager} run start\` to start developing locally. ${learnMore(
`Run ${chalk.bold(`${packageManager} run start`)} to start developing locally. ${learnMore(
'https://docs.expo.dev/get-started/start-developing/'
)}`
);
Log.withInfo(`See the README.md for more information about your project.`);
Log.withInfo(`See the ${chalk.bold('README.md')} for more information about your project.`);
}
}
+10 -2
View File
@@ -31,7 +31,6 @@ import { maybeUploadFingerprintAsync } from '../../project/maybeUploadFingerprin
import { getOwnerAccountForProjectIdAsync } from '../../project/projectUtils';
import {
RawAsset,
UpdatePublishPlatform,
buildBundlesAsync,
buildUnsortedUpdateInfoGroupAsync,
collectAssetsAsync,
@@ -51,7 +50,12 @@ import {
} from '../../project/publish';
import { resolveWorkflowPerPlatformAsync } from '../../project/workflow';
import { ensureEASUpdateIsConfiguredAsync } from '../../update/configure';
import { getUpdateJsonInfosForUpdates } from '../../update/utils';
import {
UpdatePublishPlatform,
getUpdateJsonInfosForUpdates,
isBundleDiffingEnabled,
prewarmDiffingAsync,
} from '../../update/utils';
import {
checkManifestBodyAgainstUpdateInfoGroup,
getCodeSigningInfoAsync,
@@ -571,6 +575,10 @@ export default class UpdatePublish extends EasCommand {
throw e;
}
if (isBundleDiffingEnabled(exp)) {
await prewarmDiffingAsync(graphqlClient, projectId, newUpdates);
}
if (!skipBundler && emitMetadata) {
Log.log('Generating eas-update-metadata.json');
await generateEasMetadataAsync(distRoot, getUpdateJsonInfosForUpdates(newUpdates));
@@ -7,7 +7,7 @@ import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/creat
import { EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
import Log, { learnMore } from '../../log';
import { enforceRollBackToEmbeddedUpdateSupportAsync } from '../../project/projectUtils';
import { UpdatePublishPlatform, getUpdateMessageForCommandAsync } from '../../project/publish';
import { getUpdateMessageForCommandAsync } from '../../project/publish';
import { confirmAsync, promptAsync } from '../../prompts';
import { scheduleUpdateGroupDeletionAsync } from '../../update/delete';
import {
@@ -18,6 +18,7 @@ import {
republishAsync,
} from '../../update/republish';
import { publishRollBackToEmbeddedUpdateAsync } from '../../update/roll-back-to-embedded';
import { UpdatePublishPlatform } from '../../update/utils';
import { CodeSigningInfo, getCodeSigningInfoAsync } from '../../utils/code-signing';
import { enableJsonOutput } from '../../utils/json';
import { pollForBackgroundJobReceiptAsync } from '../../utils/pollForBackgroundJobReceiptAsync';
@@ -9,7 +9,6 @@ import { StatuspageServiceName } from '../../graphql/generated';
import { RequestedPlatform } from '../../platform';
import { enforceRollBackToEmbeddedUpdateSupportAsync } from '../../project/projectUtils';
import {
UpdatePublishPlatform,
defaultPublishPlatforms,
getBranchNameForCommandAsync,
getUpdateMessageForCommandAsync,
@@ -17,6 +16,7 @@ import {
import { ensureEASUpdateIsConfiguredAsync } from '../../update/configure';
import { selectRuntimeOnBranchAsync } from '../../update/queries';
import { publishRollBackToEmbeddedUpdateAsync } from '../../update/roll-back-to-embedded';
import { UpdatePublishPlatform } from '../../update/utils';
import { getCodeSigningInfoAsync } from '../../utils/code-signing';
import { enableJsonOutput } from '../../utils/json';
import { maybeWarnAboutEasOutagesAsync } from '../../utils/statuspageService';
+8 -82
View File
@@ -50,7 +50,6 @@ import slash from 'slash';
import { getWorkflowRunUrl } from '../../build/utils/url';
import EasCommand from '../../commandUtils/EasCommand';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { EASNonInteractiveFlag, EasJsonOnlyFlag } from '../../commandUtils/flags';
import {
maybePromptForMissingInputsAsync,
@@ -60,34 +59,25 @@ import {
} from '../../commandUtils/workflow/inputs';
import {
fileExistsAsync,
infoForActiveWorkflowRunAsync,
infoForFailedWorkflowRunAsync,
maybeReadStdinAsync,
showWorkflowStatusAsync,
workflowRunExitCodes,
} from '../../commandUtils/workflow/utils';
import {
WorkflowProjectSourceType,
WorkflowRevision,
WorkflowRunByIdQuery,
WorkflowRunStatus,
} from '../../graphql/generated';
import { WorkflowRevisionMutation } from '../../graphql/mutations/WorkflowRevisionMutation';
import { WorkflowRunMutation } from '../../graphql/mutations/WorkflowRunMutation';
import { WorkflowRunQuery } from '../../graphql/queries/WorkflowRunQuery';
import Log, { link } from '../../log';
import { ora } from '../../ora';
import { getOwnerAccountForProjectIdAsync } from '../../project/projectUtils';
import { uploadAccountScopedFileAsync } from '../../project/uploadAccountScopedFileAsync';
import { uploadAccountScopedProjectSourceAsync } from '../../project/uploadAccountScopedProjectSourceAsync';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
import { sleepAsync } from '../../utils/promise';
import { WorkflowFile } from '../../utils/workflowFile';
const EXIT_CODES = {
WORKFLOW_FAILED: 11,
WORKFLOW_CANCELED: 12,
WAIT_ABORTED: 13,
};
export default class WorkflowRun extends EasCommand {
static override description =
'run an EAS workflow. The entire local project directory will be packaged and uploaded to EAS servers for the workflow run, unless the --ref flag is used.';
@@ -145,7 +135,9 @@ export default class WorkflowRun extends EasCommand {
const {
projectId,
exp: { slug: projectName },
} = await getDynamicPrivateProjectConfigAsync();
} = await getDynamicPrivateProjectConfigAsync({
skipPlugins: true,
});
const account = await getOwnerAccountForProjectIdAsync(graphqlClient, projectId);
let yamlConfig: string;
@@ -369,7 +361,7 @@ export default class WorkflowRun extends EasCommand {
const spinnerUsesStdErr = boolish('CI', false) || flags.json;
const { status } = await waitForWorkflowRunToEndAsync(graphqlClient, {
const { status } = await showWorkflowStatusAsync(graphqlClient, {
workflowRunId,
spinnerUsesStdErr,
});
@@ -386,75 +378,9 @@ export default class WorkflowRun extends EasCommand {
}
if (status === WorkflowRunStatus.Failure) {
process.exit(EXIT_CODES.WORKFLOW_FAILED);
process.exit(workflowRunExitCodes.WORKFLOW_FAILED);
} else if (status === WorkflowRunStatus.Canceled) {
process.exit(EXIT_CODES.WORKFLOW_CANCELED);
process.exit(workflowRunExitCodes.WORKFLOW_CANCELED);
}
}
}
async function waitForWorkflowRunToEndAsync(
graphqlClient: ExpoGraphqlClient,
{ workflowRunId, spinnerUsesStdErr }: { workflowRunId: string; spinnerUsesStdErr: boolean }
): Promise<WorkflowRunByIdQuery['workflowRuns']['byId']> {
Log.log('Waiting for workflow run to complete. You can press Ctrl+C to exit.');
const spinner = ora({
stream: spinnerUsesStdErr ? process.stderr : process.stdout,
text: '',
}).start();
spinner.prefixText = chalk`{bold.yellow Workflow run is waiting to start:}`;
let failedFetchesCount = 0;
while (true) {
try {
const workflowRun = await WorkflowRunQuery.withJobsByIdAsync(graphqlClient, workflowRunId, {
useCache: false,
});
failedFetchesCount = 0;
switch (workflowRun.status) {
case WorkflowRunStatus.New:
break;
case WorkflowRunStatus.InProgress: {
spinner.prefixText = chalk`{bold.green Workflow run is in progress:}`;
spinner.text = await infoForActiveWorkflowRunAsync(graphqlClient, workflowRun, 5);
break;
}
case WorkflowRunStatus.ActionRequired:
spinner.prefixText = chalk`{bold.yellow Workflow run is waiting for action:}`;
break;
case WorkflowRunStatus.Canceled:
spinner.prefixText = chalk`{bold.yellow Workflow has been canceled.}`;
spinner.stopAndPersist();
return workflowRun;
case WorkflowRunStatus.Failure: {
spinner.prefixText = chalk`{bold.red Workflow has failed.}`;
const failedInfo = await infoForFailedWorkflowRunAsync(graphqlClient, workflowRun);
spinner.fail(failedInfo);
return workflowRun;
}
case WorkflowRunStatus.Success:
spinner.prefixText = chalk`{bold.green Workflow has completed successfully.}`;
spinner.text = '';
spinner.succeed('');
return workflowRun;
}
} catch {
spinner.text = '⚠ Failed to fetch the workflow run status. Check your network connection.';
failedFetchesCount += 1;
if (failedFetchesCount > 6) {
spinner.fail('Failed to fetch the workflow run status 6 times in a row. Aborting wait.');
process.exit(EXIT_CODES.WAIT_ABORTED);
}
}
await sleepAsync(10 /* seconds */ * 1000 /* milliseconds */);
}
}
@@ -0,0 +1,138 @@
/**
* EAS Workflow Status Command
*
* This command shows the status of an existing workflow run.
*
* If no run ID is provided, you will be prompted to select from recent workflow runs for the current project.
*
* If the selected run is still in progress, the command will show the progress of the run, with an option
* to show periodic status updates while waiting for completion (similar to `eas workflow:run --wait`).
*
*/
import { Flags } from '@oclif/core';
import { boolish } from 'getenv';
import { getWorkflowRunUrl } from '../../build/utils/url';
import EasCommand from '../../commandUtils/EasCommand';
import { EASNonInteractiveFlag, EasJsonOnlyFlag } from '../../commandUtils/flags';
import {
choiceFromWorkflowRun,
processWorkflowRuns,
showWorkflowStatusAsync,
workflowRunExitCodes,
} from '../../commandUtils/workflow/utils';
import { WorkflowRunStatus } from '../../graphql/generated';
import { AppQuery } from '../../graphql/queries/AppQuery';
import { WorkflowRunQuery } from '../../graphql/queries/WorkflowRunQuery';
import Log, { link } from '../../log';
import { getOwnerAccountForProjectIdAsync } from '../../project/projectUtils';
import { promptAsync } from '../../prompts';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
export default class WorkflowStatus extends EasCommand {
static override description =
'show the status of an existing workflow run. If no run ID is provided, you will be prompted to select from recent workflow runs for the current project.';
static override args = [
{
name: 'WORKFLOW_RUN_ID',
description: 'A workflow run ID.',
},
];
static override flags = {
...EASNonInteractiveFlag,
wait: Flags.boolean({
default: false,
allowNo: true,
description: 'Exit codes: 0 = success, 11 = failure, 12 = canceled, 13 = wait aborted.',
summary: 'Wait for workflow run to complete. Defaults to false.',
}),
...EasJsonOnlyFlag,
};
static override contextDefinition = {
...this.ContextOptions.DynamicProjectConfig,
...this.ContextOptions.ProjectDir,
...this.ContextOptions.Vcs,
...this.ContextOptions.LoggedIn,
};
async runAsync(): Promise<void> {
const { flags, args } = await this.parse(WorkflowStatus);
if (flags.json) {
enableJsonOutput();
}
const {
getDynamicPrivateProjectConfigAsync,
loggedIn: { graphqlClient },
} = await this.getContextAsync(WorkflowStatus, {
nonInteractive: flags['non-interactive'],
withServerSideEnvironment: null,
});
const {
projectId,
exp: { slug: projectName },
} = await getDynamicPrivateProjectConfigAsync();
const account = await getOwnerAccountForProjectIdAsync(graphqlClient, projectId);
let workflowRunId = args.WORKFLOW_RUN_ID;
if (!workflowRunId && flags['non-interactive']) {
throw new Error('Workflow run ID is required in non-interactive mode');
}
if (!workflowRunId) {
const queryResult = await AppQuery.byIdWorkflowRunsFilteredByStatusAsync(
graphqlClient,
projectId,
undefined,
50
);
const runs = processWorkflowRuns(queryResult);
if (runs.length === 0) {
Log.warn('No workflow runs to show');
return;
}
const answers = await promptAsync({
type: 'select',
name: 'selectedRun',
message: 'Select a workflow run:',
choices: runs.map(run => choiceFromWorkflowRun(run)),
});
workflowRunId = answers.selectedRun;
}
Log.addNewLineIfNone();
Log.log(`See logs: ${link(getWorkflowRunUrl(account.name, projectName, workflowRunId))}`);
Log.addNewLineIfNone();
const spinnerUsesStdErr = boolish('CI', false) || flags.json;
await showWorkflowStatusAsync(graphqlClient, {
workflowRunId,
spinnerUsesStdErr,
waitForCompletion: flags.wait,
});
const workflowRun = await WorkflowRunQuery.withJobsByIdAsync(graphqlClient, workflowRunId, {
useCache: false,
});
const status = workflowRun.status;
if (flags.json) {
printJsonOnlyOutput({
...workflowRun,
url: getWorkflowRunUrl(account.name, projectName, workflowRunId),
});
}
if (status === WorkflowRunStatus.Failure) {
process.exit(workflowRunExitCodes.WORKFLOW_FAILED);
} else if (status === WorkflowRunStatus.Canceled) {
process.exit(workflowRunExitCodes.WORKFLOW_CANCELED);
}
}
}
+377 -9
View File
@@ -159,6 +159,7 @@ export type Account = {
pendingSentryInstallation?: Maybe<PendingSentryInstallation>;
profileImageUrl: Scalars['String']['output'];
pushSecurityEnabled: Scalars['Boolean']['output'];
requireTwoFactor: Scalars['Boolean']['output'];
/** @deprecated Legacy access tokens are deprecated */
requiresAccessTokenForPushSecurity: Scalars['Boolean']['output'];
sentryInstallation?: Maybe<SentryInstallation>;
@@ -186,8 +187,11 @@ export type Account = {
userActorOwner?: Maybe<UserActor>;
/** Pending user invitations for this account */
userInvitations: Array<UserInvitation>;
userSpecifiedAccountUsage?: Maybe<UserSpecifiedAccountUsage>;
/** Actors associated with this account and permissions they hold */
users: Array<UserPermission>;
/** Vexo account connection for this account */
vexoAccountConnection?: Maybe<VexoAccountConnection>;
/** Notification preferences of the viewer for this account */
viewerNotificationPreferences: Array<NotificationPreferenceItem>;
/** Permission info for the viewer on this account */
@@ -541,6 +545,7 @@ export enum AccountAppsSortByField {
export type AccountDataInput = {
displayName?: InputMaybe<Scalars['String']['input']>;
name: Scalars['String']['input'];
userSpecifiedAccountUsage?: InputMaybe<UserSpecifiedAccountUsage>;
};
export type AccountGoogleServiceAccountKeysConnection = {
@@ -579,6 +584,15 @@ export type AccountMutation = {
setDisplayName: Account;
/** Require authorization to send push notifications for experiences owned by this account */
setPushSecurityEnabled: Account;
/**
* Set whether two-factor authentication is required for this account. When enabled:
* - Existing members with 2FA cannot disable it
* - New members must enable 2FA before joining
* - Existing members without 2FA are not affected
*/
setRequireTwoFactor: Account;
/** Set the user specified account usage for the account. */
setUserSpecifiedAccountUsage: Account;
};
@@ -649,6 +663,18 @@ export type AccountMutationSetPushSecurityEnabledArgs = {
pushSecurityEnabled: Scalars['Boolean']['input'];
};
export type AccountMutationSetRequireTwoFactorArgs = {
accountID: Scalars['ID']['input'];
requireTwoFactor: Scalars['Boolean']['input'];
};
export type AccountMutationSetUserSpecifiedAccountUsageArgs = {
accountID: Scalars['ID']['input'];
userSpecifiedAccountUsage: UserSpecifiedAccountUsage;
};
/** Account-level notification preference */
export type AccountNotificationPreference = NotificationPreference & {
__typename?: 'AccountNotificationPreference';
@@ -1287,6 +1313,7 @@ export type App = Project & {
appStoreUrl?: Maybe<Scalars['String']['output']>;
assetLimitPerUpdateGroup: Scalars['Int']['output'];
branchesPaginated: AppBranchesConnection;
buildProfiles: Array<Scalars['String']['output']>;
/** (EAS Build) Builds associated with this app */
builds: Array<Build>;
buildsPaginated: AppBuildsConnection;
@@ -1434,6 +1461,7 @@ export type App = Project & {
username: Scalars['String']['output'];
/** @deprecated No longer supported */
users?: Maybe<Array<Maybe<User>>>;
vexoApp?: Maybe<VexoApp>;
/** Notification preferences of the viewer for this app */
viewerNotificationPreferences: Array<NotificationPreferenceItem>;
/** Webhooks for an app */
@@ -1450,6 +1478,7 @@ export type App = Project & {
workflowRunGitBranchesPaginated: AppWorkflowRunGitBranchesConnection;
workflowRunsPaginated: AppWorkflowRunsConnection;
workflows: Array<Workflow>;
workflowsInsights: AppWorkflowsInsights;
};
@@ -2271,6 +2300,7 @@ export type AppWorkflowRunEdge = {
export type AppWorkflowRunFilterInput = {
requestedGitRef?: InputMaybe<Scalars['String']['input']>;
status?: InputMaybe<WorkflowRunStatus>;
timeRange?: InputMaybe<WorkflowRunTimeRangeInput>;
};
export type AppWorkflowRunGitBranchEdge = {
@@ -2291,12 +2321,45 @@ export type AppWorkflowRunGitBranchesConnection = {
pageInfo: PageInfo;
};
export type AppWorkflowRunTimeRangeInput = {
earliest?: InputMaybe<Scalars['DateTime']['input']>;
latest?: InputMaybe<Scalars['DateTime']['input']>;
};
export type AppWorkflowRunsConnection = {
__typename?: 'AppWorkflowRunsConnection';
edges: Array<AppWorkflowRunEdge>;
pageInfo: PageInfo;
};
export type AppWorkflowsInsights = {
__typename?: 'AppWorkflowsInsights';
overviewMetrics: WorkflowsInsightsOverviewMetrics;
runsOverTime: WorkflowsInsightsRunsOverTimeData;
workflows: WorkflowsInsightsWorkflowConnection;
};
export type AppWorkflowsInsightsOverviewMetricsArgs = {
filters?: InputMaybe<WorkflowsInsightsFiltersInput>;
timespan: WorkflowsInsightsTimespanInput;
};
export type AppWorkflowsInsightsRunsOverTimeArgs = {
filters?: InputMaybe<WorkflowsInsightsFiltersInput>;
granularity: WorkflowsInsightsRunsOverTimeGranularity;
timespan: WorkflowsInsightsTimespanInput;
};
export type AppWorkflowsInsightsWorkflowsArgs = {
after?: InputMaybe<Scalars['String']['input']>;
filters?: InputMaybe<WorkflowsInsightsFiltersInput>;
first: Scalars['Int']['input'];
timespan: WorkflowsInsightsTimespanInput;
};
export type AppleAppIdentifier = {
__typename?: 'AppleAppIdentifier';
account: Account;
@@ -3148,6 +3211,8 @@ export type BuildFilter = {
};
export type BuildFilterInput = {
buildModes?: InputMaybe<Array<BuildMode>>;
buildProfile?: InputMaybe<Scalars['String']['input']>;
channel?: InputMaybe<Scalars['String']['input']>;
developmentClient?: InputMaybe<Scalars['Boolean']['input']>;
distributions?: InputMaybe<Array<DistributionType>>;
@@ -3708,6 +3773,21 @@ export type CreateSubmissionResult = {
submission: Submission;
};
export type CreateVexoAccountConnectionInput = {
accountId: Scalars['ID']['input'];
code: Scalars['String']['input'];
};
export type CreateVexoAppInput = {
appId: Scalars['ID']['input'];
domain?: InputMaybe<Scalars['String']['input']>;
iconUrl?: InputMaybe<Scalars['String']['input']>;
name: Scalars['String']['input'];
owner: Scalars['String']['input'];
slug: Scalars['String']['input'];
vexoIdentifier: Scalars['String']['input'];
};
export type CumulativeAverageMetrics = {
__typename?: 'CumulativeAverageMetrics';
averageUpdatePayloadBytes: Scalars['Int']['output'];
@@ -6323,6 +6403,12 @@ export type RootMutation = {
userDashboardViewPins: UserDashboardViewPinMutation;
/** Mutations that create, delete, and accept UserInvitations */
userInvitation: UserInvitationMutation;
/** Mutation interface for user preferences */
userPreference: UserPreferenceMutation;
/** Mutations for Vexo account connections */
vexoAccountConnection: VexoAccountConnectionMutation;
/** Mutations for Vexo apps */
vexoApp: VexoAppMutation;
/** Mutations that create, delete, update Webhooks */
webhook: WebhookMutation;
/** Mutations that modify a websiteNotification */
@@ -6455,6 +6541,10 @@ export type RootQuery = {
userByUsername?: Maybe<User>;
/** Top-level query object for querying UserInvitationPublicData publicly. */
userInvitationPublicData: UserInvitationPublicDataQuery;
/** Query interface for user preferences */
userPreference: UserPreferenceQuery;
/** Top-level query object for querying Vexo Integration information. */
vexoIntegration: VexoIntegrationQuery;
/**
* If authenticated as a typical end user, this is the appropriate top-level
* query object
@@ -7239,6 +7329,7 @@ export type UpdateBranch = {
name: Scalars['String']['output'];
runtimes: RuntimesConnection;
updateGroups: Array<Array<Update>>;
updateGroupsPaginated: UpdateGroupsConnection;
updatedAt: Scalars['DateTime']['output'];
updates: Array<Update>;
};
@@ -7260,6 +7351,15 @@ export type UpdateBranchUpdateGroupsArgs = {
};
export type UpdateBranchUpdateGroupsPaginatedArgs = {
after?: InputMaybe<Scalars['String']['input']>;
before?: InputMaybe<Scalars['String']['input']>;
filter?: InputMaybe<UpdatesFilterV2>;
first?: InputMaybe<Scalars['Int']['input']>;
last?: InputMaybe<Scalars['Int']['input']>;
};
export type UpdateBranchUpdatesArgs = {
filter?: InputMaybe<UpdatesFilter>;
limit: Scalars['Int']['input'];
@@ -7270,7 +7370,10 @@ export type UpdateBranchMutation = {
__typename?: 'UpdateBranchMutation';
/** Create an EAS branch for an app */
createUpdateBranchForApp: UpdateBranch;
/** Delete an EAS branch and all of its updates as long as the branch is not being used by any channels */
/**
* Delete an EAS branch and all of its updates as long as the branch is not being used by any channels
* @deprecated Use scheduleUpdateBranchDeletion instead
*/
deleteUpdateBranch: DeleteUpdateBranchResult;
/**
* Edit an EAS branch. The branch can be specified either by its ID or
@@ -7279,6 +7382,8 @@ export type UpdateBranchMutation = {
editUpdateBranch: UpdateBranch;
/** Publish an update group to a branch */
publishUpdateGroups: Array<Update>;
/** Delete an EAS branch and all of its updates in the background */
scheduleUpdateBranchDeletion: BackgroundJobReceipt;
};
@@ -7302,6 +7407,11 @@ export type UpdateBranchMutationPublishUpdateGroupsArgs = {
publishUpdateGroupsInput: Array<PublishUpdateGroupInput>;
};
export type UpdateBranchMutationScheduleUpdateBranchDeletionArgs = {
branchId: Scalars['ID']['input'];
};
export type UpdateChannel = {
__typename?: 'UpdateChannel';
app: App;
@@ -7467,6 +7577,18 @@ export type UpdateGitHubRepositorySettingsInput = {
baseDirectory: Scalars['String']['input'];
};
export type UpdateGroupEdge = {
__typename?: 'UpdateGroupEdge';
cursor: Scalars['String']['output'];
node: Array<Update>;
};
export type UpdateGroupsConnection = {
__typename?: 'UpdateGroupsConnection';
edges: Array<UpdateGroupEdge>;
pageInfo: PageInfo;
};
export type UpdateInfoGroup = {
android?: InputMaybe<PartialManifest>;
ios?: InputMaybe<PartialManifest>;
@@ -7557,10 +7679,22 @@ export type UpdateRolloutInfoGroup = {
web?: InputMaybe<UpdateRolloutInfo>;
};
export type UpdateVexoAppInput = {
domain?: InputMaybe<Scalars['String']['input']>;
iconUrl?: InputMaybe<Scalars['String']['input']>;
name?: InputMaybe<Scalars['String']['input']>;
owner?: InputMaybe<Scalars['String']['input']>;
slug?: InputMaybe<Scalars['String']['input']>;
};
export type UpdatesFilter = {
platform?: InputMaybe<AppPlatform>;
runtimeVersions?: InputMaybe<Array<Scalars['String']['input']>>;
sdkVersions?: InputMaybe<Array<Scalars['String']['input']>>;
};
export type UpdatesFilterV2 = {
platform?: InputMaybe<AppPlatform>;
runtimeVersions?: InputMaybe<Array<Scalars['String']['input']>>;
};
export type UpdatesMetricsData = {
@@ -8096,6 +8230,8 @@ export type UserInvitation = {
* @deprecated Use accountProfileImageUrl
*/
accountProfilePhoto?: Maybe<Scalars['String']['output']>;
/** Whether the account requires two-factor authentication */
accountRequiresTwoFactor: Scalars['Boolean']['output'];
created: Scalars['DateTime']['output'];
/** Email to which this invitation was sent */
email: Scalars['String']['output'];
@@ -8181,6 +8317,7 @@ export type UserInvitationPublicData = {
accountName: Scalars['String']['output'];
accountProfileImageUrl: Scalars['String']['output'];
accountProfilePhoto?: Maybe<Scalars['String']['output']>;
accountRequiresTwoFactor: Scalars['Boolean']['output'];
created: Scalars['DateTime']['output'];
email: Scalars['String']['output'];
expires: Scalars['DateTime']['output'];
@@ -8216,6 +8353,51 @@ export type UserPermission = {
userActor?: Maybe<UserActor>;
};
/** A single user preference key-value pair */
export type UserPreference = {
__typename?: 'UserPreference';
createdAt: Scalars['DateTime']['output'];
id: Scalars['ID']['output'];
key: Scalars['String']['output'];
updatedAt: Scalars['DateTime']['output'];
value: Scalars['JSON']['output'];
};
/** Mutation interface for user preferences */
export type UserPreferenceMutation = {
__typename?: 'UserPreferenceMutation';
/** Delete a user preference by key */
delete?: Maybe<UserPreference>;
/** Set a user preference value by key */
set: UserPreference;
};
/** Mutation interface for user preferences */
export type UserPreferenceMutationDeleteArgs = {
key: Scalars['String']['input'];
};
/** Mutation interface for user preferences */
export type UserPreferenceMutationSetArgs = {
key: Scalars['String']['input'];
value: Scalars['JSON']['input'];
};
/** Query interface for user preferences */
export type UserPreferenceQuery = {
__typename?: 'UserPreferenceQuery';
/** Get a user preference by key */
get?: Maybe<UserPreference>;
};
/** Query interface for user preferences */
export type UserPreferenceQueryGetArgs = {
key: Scalars['String']['input'];
};
export type UserPreferences = {
__typename?: 'UserPreferences';
onboarding?: Maybe<UserPreferencesOnboarding>;
@@ -8296,6 +8478,86 @@ export type UserSecondFactorDevice = {
user: User;
};
export enum UserSpecifiedAccountUsage {
Company = 'COMPANY',
Personal = 'PERSONAL'
}
export type VexoAccountAccessToken = {
__typename?: 'VexoAccountAccessToken';
access_token: Scalars['String']['output'];
expires_at?: Maybe<Scalars['String']['output']>;
token_type: Scalars['String']['output'];
};
export type VexoAccountConnection = {
__typename?: 'VexoAccountConnection';
accessToken: VexoAccountAccessToken;
account: Account;
id: Scalars['ID']['output'];
};
export type VexoAccountConnectionMutation = {
__typename?: 'VexoAccountConnectionMutation';
/** Create a Vexo account connection for an Account */
createVexoAccountConnection: VexoAccountConnection;
/** Delete a Vexo account connection by ID and revoke the access token */
revokeAndDeleteVexoAccountConnection: VexoAccountConnection;
};
export type VexoAccountConnectionMutationCreateVexoAccountConnectionArgs = {
vexoAccountConnectionData: CreateVexoAccountConnectionInput;
};
export type VexoAccountConnectionMutationRevokeAndDeleteVexoAccountConnectionArgs = {
vexoAccountConnectionId: Scalars['ID']['input'];
};
export type VexoApp = {
__typename?: 'VexoApp';
app: App;
domain?: Maybe<Scalars['String']['output']>;
iconUrl?: Maybe<Scalars['String']['output']>;
id: Scalars['ID']['output'];
name: Scalars['String']['output'];
owner: Scalars['String']['output'];
slug: Scalars['String']['output'];
vexoIdentifier: Scalars['String']['output'];
};
export type VexoAppMutation = {
__typename?: 'VexoAppMutation';
/** Create a Vexo app for an App */
createVexoApp: VexoApp;
/** Delete a Vexo app by ID */
deleteVexoApp: VexoApp;
/** Update a Vexo app by ID */
updateVexoApp: VexoApp;
};
export type VexoAppMutationCreateVexoAppArgs = {
vexoAppData: CreateVexoAppInput;
};
export type VexoAppMutationDeleteVexoAppArgs = {
vexoAppId: Scalars['ID']['input'];
};
export type VexoAppMutationUpdateVexoAppArgs = {
vexoAppData: UpdateVexoAppInput;
vexoAppId: Scalars['ID']['input'];
};
export type VexoIntegrationQuery = {
__typename?: 'VexoIntegrationQuery';
clientIdentifier: Scalars['String']['output'];
};
export type WebNotificationUpdateReadStateInput = {
id: Scalars['ID']['input'];
isRead: Scalars['Boolean']['input'];
@@ -8835,6 +9097,7 @@ export type Workflow = {
createdAt: Scalars['DateTime']['output'];
fileName: Scalars['String']['output'];
id: Scalars['ID']['output'];
insights: WorkflowsInsightsWorkflowMetrics;
name?: Maybe<Scalars['String']['output']>;
revisionsPaginated: WorkflowRevisionsConnection;
runsPaginated: WorkflowRunsConnection;
@@ -8842,6 +9105,12 @@ export type Workflow = {
};
export type WorkflowInsightsArgs = {
filters?: InputMaybe<WorkflowsInsightsFiltersInput>;
timespan: WorkflowsInsightsTimespanInput;
};
export type WorkflowRevisionsPaginatedArgs = {
after?: InputMaybe<Scalars['String']['input']>;
before?: InputMaybe<Scalars['String']['input']>;
@@ -8882,6 +9151,7 @@ export type WorkflowJob = {
approvals: Array<WorkflowJobApproval>;
createdAt: Scalars['DateTime']['output'];
credentialsAppleDeviceRegistrationRequest?: Maybe<AppleDeviceRegistrationRequest>;
environment?: Maybe<Scalars['String']['output']>;
errors: Array<WorkflowJobError>;
id: Scalars['ID']['output'];
key: Scalars['String']['output'];
@@ -9024,6 +9294,7 @@ export type WorkflowRevisionInput = {
export type WorkflowRevisionMutation = {
__typename?: 'WorkflowRevisionMutation';
getOrCreateWorkflowRevisionFromGitRef: WorkflowRevision;
getWorkflowRevisionsFromGitRef: Array<WorkflowRevision>;
validateWorkflowYamlConfig: Scalars['Boolean']['output'];
};
@@ -9035,6 +9306,12 @@ export type WorkflowRevisionMutationGetOrCreateWorkflowRevisionFromGitRefArgs =
};
export type WorkflowRevisionMutationGetWorkflowRevisionsFromGitRefArgs = {
appId: Scalars['ID']['input'];
gitRef: Scalars['String']['input'];
};
export type WorkflowRevisionMutationValidateWorkflowYamlConfigArgs = {
appId: Scalars['ID']['input'];
yamlConfig: Scalars['String']['input'];
@@ -9099,6 +9376,7 @@ export type WorkflowRunError = {
export type WorkflowRunFilterInput = {
requestedGitRef?: InputMaybe<Scalars['String']['input']>;
status?: InputMaybe<WorkflowRunStatus>;
timeRange?: InputMaybe<WorkflowRunTimeRangeInput>;
};
export type WorkflowRunGitBranchFilterInput = {
@@ -9162,6 +9440,11 @@ export enum WorkflowRunStatus {
Success = 'SUCCESS'
}
export type WorkflowRunTimeRangeInput = {
earliest?: InputMaybe<Scalars['DateTime']['input']>;
latest?: InputMaybe<Scalars['DateTime']['input']>;
};
export enum WorkflowRunTriggerEventType {
GithubPullRequestLabeled = 'GITHUB_PULL_REQUEST_LABELED',
GithubPullRequestOpened = 'GITHUB_PULL_REQUEST_OPENED',
@@ -9178,6 +9461,73 @@ export type WorkflowRunsConnection = {
pageInfo: PageInfo;
};
export type WorkflowsInsightsFiltersInput = {
gitRefRequested?: InputMaybe<Array<Scalars['String']['input']>>;
statuses?: InputMaybe<Array<WorkflowRunStatus>>;
triggerEventTypes?: InputMaybe<Array<WorkflowRunTriggerEventType>>;
workflowIds?: InputMaybe<Array<Scalars['ID']['input']>>;
};
export type WorkflowsInsightsMetric = {
__typename?: 'WorkflowsInsightsMetric';
currentValue: Scalars['Float']['output'];
previousValue: Scalars['Float']['output'];
};
export type WorkflowsInsightsOverviewMetrics = {
__typename?: 'WorkflowsInsightsOverviewMetrics';
activeWorkflows: WorkflowsInsightsMetric;
failedRuns: WorkflowsInsightsMetric;
successfulRuns: WorkflowsInsightsMetric;
totalRuns: WorkflowsInsightsMetric;
};
export type WorkflowsInsightsRunsOverTimeData = {
__typename?: 'WorkflowsInsightsRunsOverTimeData';
lineChart: LineChartData;
};
export enum WorkflowsInsightsRunsOverTimeGranularity {
Day = 'DAY',
Hour = 'HOUR',
Minute = 'MINUTE'
}
export type WorkflowsInsightsTimespanInput = {
end: Scalars['DateTime']['input'];
start: Scalars['DateTime']['input'];
};
export type WorkflowsInsightsWorkflowConnection = {
__typename?: 'WorkflowsInsightsWorkflowConnection';
edges: Array<WorkflowsInsightsWorkflowEdge>;
pageInfo: PageInfo;
};
export type WorkflowsInsightsWorkflowEdge = {
__typename?: 'WorkflowsInsightsWorkflowEdge';
cursor: Scalars['String']['output'];
node: WorkflowsInsightsWorkflowNode;
};
export type WorkflowsInsightsWorkflowMetrics = {
__typename?: 'WorkflowsInsightsWorkflowMetrics';
failedRuns: WorkflowsInsightsMetric;
lastRunAt?: Maybe<Scalars['DateTime']['output']>;
successfulRuns: WorkflowsInsightsMetric;
totalRuns: WorkflowsInsightsMetric;
};
export type WorkflowsInsightsWorkflowNode = {
__typename?: 'WorkflowsInsightsWorkflowNode';
failedRuns: Scalars['Int']['output'];
lastRunAt: Scalars['DateTime']['output'];
name: Scalars['String']['output'];
successfulRuns: Scalars['Int']['output'];
totalRuns: Scalars['Int']['output'];
workflowId: Scalars['ID']['output'];
};
export type DeleteAndroidAppBuildCredentialsResult = {
__typename?: 'deleteAndroidAppBuildCredentialsResult';
id: Scalars['ID']['output'];
@@ -9198,6 +9548,13 @@ export type DeleteApplePushKeyResult = {
id: Scalars['ID']['output'];
};
export type ScheduleBranchDeletionMutationVariables = Exact<{
branchId: Scalars['ID']['input'];
}>;
export type ScheduleBranchDeletionMutation = { __typename?: 'RootMutation', updateBranch: { __typename?: 'UpdateBranchMutation', scheduleUpdateBranchDeletion: { __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 CreateUpdateBranchForAppMutationVariables = Exact<{
appId: Scalars['ID']['input'];
name: Scalars['String']['input'];
@@ -9223,13 +9580,6 @@ export type GetBranchInfoQueryVariables = Exact<{
export type GetBranchInfoQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateBranchByName?: { __typename?: 'UpdateBranch', id: string, name: string } | null } } };
export type DeleteUpdateBranchMutationVariables = Exact<{
branchId: Scalars['ID']['input'];
}>;
export type DeleteUpdateBranchMutation = { __typename?: 'RootMutation', updateBranch: { __typename?: 'UpdateBranchMutation', deleteUpdateBranch: { __typename?: 'DeleteUpdateBranchResult', id: string } } };
export type EditUpdateBranchMutationVariables = Exact<{
input: EditUpdateBranchInput;
}>;
@@ -9936,6 +10286,14 @@ export type DeleteWebhookMutationVariables = Exact<{
export type DeleteWebhookMutation = { __typename?: 'RootMutation', webhook: { __typename?: 'WebhookMutation', deleteWebhook: { __typename?: 'DeleteWebhookResult', id: string } } };
export type GetWorkflowRevisionsFromGitRefMutationVariables = Exact<{
appId: Scalars['ID']['input'];
gitRef: Scalars['String']['input'];
}>;
export type GetWorkflowRevisionsFromGitRefMutation = { __typename?: 'RootMutation', workflowRevision: { __typename?: 'WorkflowRevisionMutation', getWorkflowRevisionsFromGitRef: Array<{ __typename?: 'WorkflowRevision', id: string, yamlConfig: string, blobSha: string, commitSha?: string | null, createdAt: any, workflow: { __typename?: 'Workflow', id: string } }> } };
export type GetOrCreateWorkflowRevisionFromGitRefMutationVariables = Exact<{
appId: Scalars['ID']['input'];
fileName: Scalars['String']['input'];
@@ -10032,6 +10390,14 @@ export type LatestAppVersionQueryVariables = Exact<{
export type LatestAppVersionQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, latestAppVersionByPlatformAndApplicationIdentifier?: { __typename?: 'AppVersion', id: string, storeVersion: string, buildVersion: string } | null } } };
export type GetAssetSignedUrlsQueryVariables = Exact<{
updateId: Scalars['ID']['input'];
storageKeys: Array<Scalars['String']['input']> | Scalars['String']['input'];
}>;
export type GetAssetSignedUrlsQuery = { __typename?: 'RootQuery', asset: { __typename?: 'AssetQuery', signedUrls: Array<{ __typename?: 'AssetSignedUrlResult', storageKey: string, url: string, headers?: any | null }> } };
export type BackgroundJobReceiptByIdQueryVariables = Exact<{
id: Scalars['ID']['input'];
}>;
@@ -10052,6 +10418,8 @@ export type ViewLatestUpdateOnBranchQueryVariables = Exact<{
branchName: Scalars['String']['input'];
platform: AppPlatform;
runtimeVersion: Scalars['String']['input'];
offset: Scalars['Int']['input'];
limit: Scalars['Int']['input'];
}>;
@@ -6,6 +6,8 @@ import { withErrorHandlingAsync } from '../client';
import {
GetOrCreateWorkflowRevisionFromGitRefMutation,
GetOrCreateWorkflowRevisionFromGitRefMutationVariables,
GetWorkflowRevisionsFromGitRefMutation,
GetWorkflowRevisionsFromGitRefMutationVariables,
ValidateWorkflowYamlConfigMutation,
ValidateWorkflowYamlConfigMutationVariables,
WorkflowRevision,
@@ -19,7 +21,53 @@ export namespace WorkflowRevisionMutation {
fieldErrors: z.record(z.string(), z.array(z.string())),
}),
});
export async function getWorkflowRevisionsFromGitRefAsync(
graphqlClient: ExpoGraphqlClient,
{
appId,
gitRef,
}: {
appId: string;
gitRef: string;
}
): Promise<WorkflowRevision[] | undefined> {
const data = await withErrorHandlingAsync(
graphqlClient
.mutation<
GetWorkflowRevisionsFromGitRefMutation,
GetWorkflowRevisionsFromGitRefMutationVariables
>(
gql`
mutation GetWorkflowRevisionsFromGitRef($appId: ID!, $gitRef: String!) {
workflowRevision {
getWorkflowRevisionsFromGitRef(appId: $appId, gitRef: $gitRef) {
id
yamlConfig
blobSha
commitSha
createdAt
workflow {
id
app {
id
name
slug
}
fileName
}
}
}
}
`,
{
appId,
gitRef,
}
)
.toPromise()
);
return (data.workflowRevision?.getWorkflowRevisionsFromGitRef as WorkflowRevision[]) ?? [];
}
export async function getOrCreateWorkflowRevisionFromGitRefAsync(
graphqlClient: ExpoGraphqlClient,
{
@@ -0,0 +1,41 @@
import gql from 'graphql-tag';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { withErrorHandlingAsync } from '../client';
import {
AssetSignedUrlResult,
GetAssetSignedUrlsQuery,
GetAssetSignedUrlsQueryVariables,
} from '../generated';
export const AssetQuery = {
async getSignedUrlsAsync(
graphqlClient: ExpoGraphqlClient,
updateId: string,
storageKeys: string[]
): Promise<AssetSignedUrlResult[]> {
const data = await withErrorHandlingAsync(
graphqlClient
.query<GetAssetSignedUrlsQuery, GetAssetSignedUrlsQueryVariables>(
gql`
query GetAssetSignedUrls($updateId: ID!, $storageKeys: [String!]!) {
asset {
signedUrls(updateId: $updateId, storageKeys: $storageKeys) {
storageKey
url
headers
}
}
}
`,
{
updateId,
storageKeys,
},
{ additionalTypenames: [] }
)
.toPromise()
);
return data.asset.signedUrls;
},
};
@@ -63,15 +63,24 @@ export const BranchQuery = {
}
return updateBranchByName;
},
async getLatestUpdateIdOnBranchAsync(
async getUpdateIdsOnBranchAsync(
graphqlClient: ExpoGraphqlClient,
{
appId,
branchName,
platform,
runtimeVersion,
}: { appId: string; branchName: string; platform: AppPlatform; runtimeVersion: string }
): Promise<string | null> {
offset = 0,
limit = 1,
}: {
appId: string;
branchName: string;
platform: AppPlatform;
runtimeVersion: string;
offset?: number;
limit?: number;
}
): Promise<string[]> {
const response = await withErrorHandlingAsync(
graphqlClient
.query<ViewLatestUpdateOnBranchQuery, ViewLatestUpdateOnBranchQueryVariables>(
@@ -81,6 +90,8 @@ export const BranchQuery = {
$branchName: String!
$platform: AppPlatform!
$runtimeVersion: String!
$offset: Int!
$limit: Int!
) {
app {
byId(appId: $appId) {
@@ -88,8 +99,8 @@ export const BranchQuery = {
updateBranchByName(name: $branchName) {
id
updates(
offset: 0
limit: 1
offset: $offset
limit: $limit
filter: { platform: $platform, runtimeVersions: [$runtimeVersion] }
) {
id
@@ -104,6 +115,8 @@ export const BranchQuery = {
branchName,
platform,
runtimeVersion,
offset,
limit,
},
{ additionalTypenames: ['UpdateBranch'] }
)
@@ -113,11 +126,26 @@ export const BranchQuery = {
if (!updateBranchByName) {
throw new BranchNotFoundError(`Could not find a branch named "${branchName}".`);
}
const latestUpdate = updateBranchByName.updates[0];
if (!latestUpdate) {
return null;
}
return latestUpdate.id;
return updateBranchByName.updates.map(update => update.id);
},
async getLatestUpdateIdOnBranchAsync(
graphqlClient: ExpoGraphqlClient,
{
appId,
branchName,
platform,
runtimeVersion,
}: { appId: string; branchName: string; platform: AppPlatform; runtimeVersion: string }
): Promise<string | null> {
const updateIds = await this.getUpdateIdsOnBranchAsync(graphqlClient, {
appId,
branchName,
platform,
runtimeVersion,
offset: 0,
limit: 1,
});
return updateIds[0] ?? null;
},
async listBranchesOnAppAsync(
graphqlClient: ExpoGraphqlClient,
+2 -9
View File
@@ -22,7 +22,6 @@ import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGr
import { PaginatedQueryOptions } from '../commandUtils/pagination';
import { FingerprintOptions, createFingerprintsByKeyAsync } from '../fingerprint/cli';
import {
AppPlatform,
AssetMetadataStatus,
BuildFragment,
FingerprintSourceInput,
@@ -39,8 +38,10 @@ import { promptAsync } from '../prompts';
import { getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync } from '../update/getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync';
import {
UpdateJsonInfo,
UpdatePublishPlatform,
formatUpdateMessage,
truncateString as truncateUpdateMessage,
updatePublishPlatformToAppPlatform,
} from '../update/utils';
import { PresignedPost, uploadWithPresignedPostWithRetryAsync } from '../uploads';
import {
@@ -56,9 +57,6 @@ import mapMapAsync from '../utils/expodash/mapMapAsync';
import uniqBy from '../utils/expodash/uniqBy';
import { Client } from '../vcs/vcs';
// update publish does not currently support web
export type UpdatePublishPlatform = 'ios' | 'android';
type Metadata = {
version: number;
bundler: 'metro';
@@ -1049,11 +1047,6 @@ export const platformDisplayNames: Record<UpdatePublishPlatform, string> = {
ios: 'iOS',
};
export const updatePublishPlatformToAppPlatform: Record<UpdatePublishPlatform, AppPlatform> = {
android: AppPlatform.Android,
ios: AppPlatform.Ios,
};
export async function getRuntimeToUpdateRolloutInfoGroupMappingAsync(
graphqlClient: ExpoGraphqlClient,
{
@@ -5,7 +5,6 @@ import {
App,
DeploymentResult,
Runtime,
UpdateBranch,
UpdateChannel,
UpdateChannelRuntimeInsights,
UpdateInsights,
@@ -126,7 +125,7 @@ function mockUpdateChannel({
};
}
function mockUpdateBranches(branchNames: string[]): UpdateBranch[] {
function mockUpdateBranches(branchNames: string[]): any[] {
return branchNames.map(branchName => ({
id: 'f9dc4dbb-663f-4a19-8cf2-a783b484d2db',
latestActivity: '2022-12-07T02:24:29.786Z',
+1 -1
View File
@@ -2,6 +2,7 @@ import assert from 'assert';
import chalk from 'chalk';
import {
UpdatePublishPlatform,
formatBranch,
formatUpdateGroup,
formatUpdateTitle,
@@ -19,7 +20,6 @@ import {
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 {
+2 -2
View File
@@ -7,7 +7,7 @@ import {
selectRuntimeAndGetLatestUpdateGroupForEachPublishPlatformOnBranchAsync,
selectUpdateGroupOnBranchAsync,
} from './queries';
import { truncateString as truncateUpdateMessage } from './utils';
import { UpdatePublishPlatform, truncateString as truncateUpdateMessage } from './utils';
import { selectBranchOnAppAsync } from '../branch/queries';
import { getUpdateGroupUrl } from '../build/utils/url';
import { selectChannelOnAppAsync } from '../channel/queries';
@@ -20,7 +20,7 @@ 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 { getUpdateRolloutInfoGroupAsync } from '../project/publish';
import { promptAsync } from '../prompts';
import {
CodeSigningInfo,
@@ -1,7 +1,7 @@
import { ExpoConfig } from '@expo/config';
import nullthrows from 'nullthrows';
import { getUpdateJsonInfosForUpdates } from './utils';
import { UpdatePublishPlatform, getUpdateJsonInfosForUpdates } from './utils';
import { getUpdateGroupUrl } from '../build/utils/url';
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
import fetch from '../fetch';
@@ -12,7 +12,6 @@ import { ora } from '../ora';
import { getOwnerAccountForProjectIdAsync } from '../project/projectUtils';
import {
RuntimeVersionInfo,
UpdatePublishPlatform,
getRuntimeToPlatformsAndFingerprintInfoMappingFromRuntimeVersionInfoObjects,
} from '../project/publish';
import {
+88
View File
@@ -3,14 +3,19 @@ import { format } from '@expo/timeago.js';
import chalk from 'chalk';
import dateFormat from 'dateformat';
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
import {
AppPlatform,
Robot,
SsoUser,
Update,
UpdateBranchFragment,
UpdateFragment,
UpdatePublishMutation,
User,
} from '../graphql/generated';
import { AssetQuery } from '../graphql/queries/AssetQuery';
import { BranchQuery } from '../graphql/queries/BranchQuery';
import { learnMore } from '../log';
import { RequestedPlatform } from '../platform';
import { getActorDisplayName } from '../user/User';
@@ -269,3 +274,86 @@ export function getBranchDescription(branch: UpdateBranchFragment): FormattedBra
},
};
}
export function isBundleDiffingEnabled(exp: ExpoConfig): boolean {
return (exp.updates as any)?.enableBsdiffPatchSupport === true;
}
// Make authenticated requests to the launch asset URL with diffing headers
export async function prewarmDiffingAsync(
graphqlClient: ExpoGraphqlClient,
appId: string,
newUpdates: UpdatePublishMutation['updateBranch']['publishUpdateGroups']
): Promise<void> {
const DUMMY_EMBEDDED_UPDATE_ID = '00000000-0000-0000-0000-000000000000';
const toPrewarm = [] as {
update: UpdatePublishMutation['updateBranch']['publishUpdateGroups'][0];
launchAssetKey: string;
}[];
for (const update of newUpdates) {
const manifest = JSON.parse(update.manifestFragment);
const launchAssetKey: string | undefined = manifest.launchAsset?.storageKey;
const requestedUpdateId: string = update.id;
if (!launchAssetKey || !requestedUpdateId) {
continue;
}
toPrewarm.push({
update,
launchAssetKey,
});
}
await Promise.allSettled(
toPrewarm.map(async ({ update, launchAssetKey }) => {
try {
// Check to see if there's a second most recent update so we can pre-emptively generate a patch for it
const updatePublishPlatform = update.platform as UpdatePublishPlatform;
const updateIds = await BranchQuery.getUpdateIdsOnBranchAsync(graphqlClient, {
appId,
branchName: update.branch.name,
platform: updatePublishPlatformToAppPlatform[updatePublishPlatform],
runtimeVersion: update.runtimeVersion,
limit: 2,
});
if (updateIds.length !== 2) {
return;
}
const nextMostRecentUpdateId = updateIds[1];
const signed = await AssetQuery.getSignedUrlsAsync(graphqlClient, update.id, [
launchAssetKey,
]);
const first = signed?.[0];
if (!first) {
return;
}
const headers: Record<string, string> = {
...(first.headers as Record<string, string> | undefined),
'expo-current-update-id': nextMostRecentUpdateId,
'expo-requested-update-id': update.id,
'expo-embedded-update-id': DUMMY_EMBEDDED_UPDATE_ID,
'a-im': 'bsdiff',
};
await fetch(first.url, {
method: 'HEAD',
headers,
signal: AbortSignal.timeout(2500),
});
} catch {
// ignore errors, best-effort optimization
}
})
);
}
// update publish does not currently support web
export type UpdatePublishPlatform = 'ios' | 'android';
export const updatePublishPlatformToAppPlatform: Record<UpdatePublishPlatform, AppPlatform> = {
android: AppPlatform.Android,
ios: AppPlatform.Ios,
};
@@ -75,13 +75,11 @@ describe('maybeWarnAboutUsageOveragesAsync', () => {
AccountUsageQuery.getUsageForOverageWarningAsync
);
const mockWarn = jest.mocked(Log.warn);
const mockNewLine = jest.mocked(Log.newLine);
const mockDebug = jest.mocked(Log.debug);
beforeEach(() => {
mockGetUsageForOverageWarningAsync.mockClear();
mockWarn.mockClear();
mockNewLine.mockClear();
mockDebug.mockClear();
});
@@ -109,7 +107,6 @@ describe('maybeWarnAboutUsageOveragesAsync', () => {
expect(mockWarn).toHaveBeenCalledWith(
expect.stringContaining("You won't be able to start new builds once you reach the limit.")
);
expect(mockNewLine).toHaveBeenCalledTimes(1);
});
it('displays a warning for a Starter plan with high build usage', async () => {
@@ -133,7 +130,6 @@ describe('maybeWarnAboutUsageOveragesAsync', () => {
'Additional usage beyond your limit will be charged at pay-as-you-go rates.'
)
);
expect(mockNewLine).toHaveBeenCalledTimes(1);
});
it('does not display a warning when usage is below threshold', async () => {
@@ -81,5 +81,4 @@ export function displayOverageWarning({
});
Log.warn(warning);
Log.newLine();
}
Generated
+52 -51
View File
@@ -1412,7 +1412,7 @@
node-forge "^1.2.1"
nullthrows "^1.1.1"
"@expo/[email protected]", "@expo/config-plugins@~9.0.10":
"@expo/[email protected]":
version "9.0.12"
resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-9.0.12.tgz#f122b2dca22e135eadf6e73442da3ced0ce8aa0a"
integrity sha512-/Ko/NM+GzvJyRkq8PITm8ms0KY5v0wmN1OQFYRMkcJqOi3PjlhndW+G6bHpJI9mkQXBaUnHwAiGLqIC3+MQ5Wg==
@@ -1452,14 +1452,14 @@
xcode "^3.0.1"
xml2js "0.6.0"
"@expo/config-plugins@~9.0.0":
version "9.0.9"
resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-9.0.9.tgz#3765c310c112e200c6715365d6023f6a05b001ed"
integrity sha512-pbgbY3SwCMwkijhfe163J05BrTx4MqzeaV+nVgUMs7vRcjHY1tfM57Pdv6SPtgeDvZ8fvdXFXXzkJva+a7C9Bw==
"@expo/config-plugins@~9.0.0", "@expo/config-plugins@~9.0.10", "@expo/config-plugins@~9.0.17":
version "9.0.17"
resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-9.0.17.tgz#c997072209129b9f9616efa3533314b889cfd788"
integrity sha512-m24F1COquwOm7PBl5wRbkT9P9DviCXe0D7S7nQsolfbhdCWuvMkfXeoWmgjtdhy7sDlOyIgBrAdnB6MfsWKqIg==
dependencies:
"@expo/config-types" "^52.0.0"
"@expo/json-file" "~9.0.0"
"@expo/plist" "^0.2.0"
"@expo/config-types" "^52.0.5"
"@expo/json-file" "~9.0.2"
"@expo/plist" "^0.2.2"
"@expo/sdk-runtime-versions" "^1.0.0"
chalk "^4.1.2"
debug "^4.3.5"
@@ -1472,10 +1472,10 @@
xcode "^3.0.1"
xml2js "0.6.0"
"@expo/config-types@^52.0.0":
version "52.0.1"
resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-52.0.1.tgz#327af1b72a3a9d4556f41e083e0e284dd8198b96"
integrity sha512-vD8ZetyKV7U29lR6+NJohYeoLYTH+eNYXJeNiSOrWCz0witJYY11meMmEnpEaVbN89EfC6uauSUOa6wihtbyPQ==
"@expo/config-types@^52.0.0", "@expo/config-types@^52.0.5":
version "52.0.5"
resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-52.0.5.tgz#e10a226990dd903a4e3db5992ffb3015adf13f38"
integrity sha512-AMDeuDLHXXqd8W+0zSjIt7f37vUd/BP8p43k68NHpyAvQO+z8mbQZm3cNQVAMySeayK2XoPigAFB1JF2NFajaA==
"@expo/config-types@^53.0.3", "@expo/config-types@^53.0.4":
version "53.0.4"
@@ -1521,14 +1521,14 @@
sucrase "3.35.0"
"@expo/config@~10.0.4":
version "10.0.4"
resolved "https://registry.yarnpkg.com/@expo/config/-/config-10.0.4.tgz#a58ec3baef123e77584fbae769484bae2ee74f37"
integrity sha512-pkvdPqKTaP6+Qvc8aTmDLQ9Dfwp98P1GO37MFKwsF5XormfN/9/eN8HfIRoM6d3uSIVKCcWW3X2yAEbNmOyfXw==
version "10.0.11"
resolved "https://registry.yarnpkg.com/@expo/config/-/config-10.0.11.tgz#5371ccb3b08ece4c174d5d7009d61e928e6925b0"
integrity sha512-nociJ4zr/NmbVfMNe9j/+zRlt7wz/siISu7PjdWE4WE+elEGxWWxsGzltdJG0llzrM+khx8qUiFK5aiVcdMBww==
dependencies:
"@babel/code-frame" "~7.10.4"
"@expo/config-plugins" "~9.0.0"
"@expo/config-types" "^52.0.0"
"@expo/json-file" "^9.0.0"
"@expo/config-plugins" "~9.0.17"
"@expo/config-types" "^52.0.5"
"@expo/json-file" "^9.0.2"
deepmerge "^4.3.1"
getenv "^1.0.0"
glob "^10.4.2"
@@ -1571,9 +1571,9 @@
getenv "^1.0.0"
"@expo/image-utils@^0.6.0":
version "0.6.3"
resolved "https://registry.yarnpkg.com/@expo/image-utils/-/image-utils-0.6.3.tgz#89c744460beefc686989b969121357bbd5520c8a"
integrity sha512-v/JbCKBrHeudxn1gN1TgfPE/pWJSlLPrl29uXJBgrJFQVkViQvUHQNDhaS+UEa9wYI5HHh7XYmtzAehyG4L+GA==
version "0.6.5"
resolved "https://registry.yarnpkg.com/@expo/image-utils/-/image-utils-0.6.5.tgz#af25e9dd79d1168bebea91dc7f1e6f3efd28643c"
integrity sha512-RsS/1CwJYzccvlprYktD42KjyfWZECH6PPIEowvoSmXfGLfdViwcUEI4RvBfKX5Jli6P67H+6YmHvPTbGOboew==
dependencies:
"@expo/spawn-async" "^1.7.2"
chalk "^4.0.0"
@@ -1595,7 +1595,7 @@
json5 "^2.2.2"
write-file-atomic "^2.3.0"
"@expo/json-file@^9.0.0", "@expo/json-file@~9.0.0":
"@expo/json-file@^9.0.0":
version "9.0.0"
resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-9.0.0.tgz#e3688c9b108cfd7e819f1354a9458ba6e93fc943"
integrity sha512-M+55xFVrFzDcgMDf+52lPDLjKB5xwRfStWlv/b/Vu2OLgxGZLWpxoPYjlRoHqxjPbCQIi2ZCbobK+0KuNhsELg==
@@ -1604,6 +1604,14 @@
json5 "^2.2.3"
write-file-atomic "^2.3.0"
"@expo/json-file@^9.0.2":
version "9.1.5"
resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-9.1.5.tgz#7d7b2dc4990dc2c2de69a571191aba984b7fb7ed"
integrity sha512-prWBhLUlmcQtvN6Y7BpW2k9zXGd3ySa3R6rAguMJkp1z22nunLN64KYTUWfijFlprFoxm9r2VNnGkcbndAlgKA==
dependencies:
"@babel/code-frame" "~7.10.4"
json5 "^2.2.3"
"@expo/json-file@^9.1.4", "@expo/json-file@~9.1.4":
version "9.1.4"
resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-9.1.4.tgz#e719d092c08afb3234643f9285e57c6a24989327"
@@ -1612,6 +1620,15 @@
"@babel/code-frame" "~7.10.4"
json5 "^2.2.3"
"@expo/json-file@~9.0.0", "@expo/json-file@~9.0.2":
version "9.0.2"
resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-9.0.2.tgz#ec508c2ad17490e0c664c9d7e2ae0ce65915d3ed"
integrity sha512-yAznIUrybOIWp3Uax7yRflB0xsEpvIwIEqIjao9SGi2Gaa+N0OamWfe0fnXBSWF+2zzF4VvqwT4W5zwelchfgw==
dependencies:
"@babel/code-frame" "~7.10.4"
json5 "^2.2.3"
write-file-atomic "^2.3.0"
"@expo/[email protected]":
version "1.0.221"
resolved "https://registry.yarnpkg.com/@expo/logger/-/logger-1.0.221.tgz#bd6ef6e03b3c4bf0872843d8b2a83556892178c0"
@@ -1660,7 +1677,7 @@
dependencies:
node-forge "^1.2.1"
"@expo/[email protected]", "@expo/plist@^0.2.0":
"@expo/[email protected]":
version "0.2.0"
resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.2.0.tgz#beb014c0bfd56a993086c0972ec1ca3ef3f9d36c"
integrity sha512-F/IZJQaf8OIVnVA6XWUeMPC3OH6MV00Wxf0WC0JhTQht2QgjyHUa3U5Gs3vRtDq8tXNsZneOQRDVwpaOnd4zTQ==
@@ -1669,6 +1686,15 @@
base64-js "^1.2.3"
xmlbuilder "^14.0.0"
"@expo/plist@^0.2.0", "@expo/plist@^0.2.2":
version "0.2.2"
resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.2.2.tgz#2563b71b4aa78dc9dbc34cc3d2e1011e994bc9cd"
integrity sha512-ZZGvTO6vEWq02UAPs3LIdja+HRO18+LRI5QuDl6Hs3Ps7KX7xU6Y6kjahWKY37Rx2YjNpX07dGpBFzzC+vKa2g==
dependencies:
"@xmldom/xmldom" "~0.7.7"
base64-js "^1.2.3"
xmlbuilder "^14.0.0"
"@expo/plist@^0.3.4":
version "0.3.4"
resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.3.4.tgz#0c48eeff2158cf26c5c9ed4f681d24997ccfbeca"
@@ -13831,16 +13857,7 @@ string-length@^5.0.1:
char-regex "^2.0.0"
strip-ansi "^7.0.1"
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.2.3:
"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -13996,7 +14013,7 @@ string_decoder@~1.1.1:
dependencies:
safe-buffer "~5.1.0"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -14017,13 +14034,6 @@ strip-ansi@^6.0.0:
dependencies:
ansi-regex "^5.0.0"
strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2"
@@ -15243,16 +15253,7 @@ wordwrap@^1.0.0:
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
[email protected], wrap-ansi@^7.0.0:
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", [email protected], wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==