Compare commits

...
7 Commits
Author SHA1 Message Date
Stanisław Chmiela da727ba170 v13.3.0 2024-11-18 22:35:12 +01:00
4571910c4d Adds workflow:create command (#2678)
# Why

Adds `eas workflow:create` to make it faster to create workflow files in a project. This command creates a file like **.eas/workflows/workflow.yml**. The user can choose the file name or can provide it as an arugment.

# Screenshots

<img width="552" alt="Screenshot 2024-11-08 at 8 50 58 AM" src="https://github.com/user-attachments/assets/5cf82e7e-cce6-4098-b291-fccdac25f103">
<img width="584" alt="Screenshot 2024-11-08 at 8 51 27 AM" src="https://github.com/user-attachments/assets/d6f6e7cb-18c1-420e-b52a-5bdd42446715">
<img width="617" alt="Screenshot 2024-11-08 at 8 52 04 AM" src="https://github.com/user-attachments/assets/81cc79cf-afb7-4855-bfce-0679f98655fa">

# Test Plan

Make sure that you can run the command as pictured above and that it correctly creates the workflow file. Also make sure that the unit tests pass.

# Future

Once we have docs for workflows that are public, I'd like to put a link to the docs in the default file this command creates. For now, I am just putting Hello World as a reasonable placeholder.

Co-authored-by: Szymon Dziedzic <[email protected]>
Co-authored-by: Stanisław Chmiela <[email protected]>
2024-11-18 22:34:39 +01:00
Stanisław Chmiela c7cfcafff8 Fix changelog (#2701) 2024-11-18 22:29:41 +01:00
Stanisław Chmiela 6f913f7320 Update CHANGELOG.md 2024-11-18 19:33:54 +01:00
Stanisław Chmiela 0a49296231 [eas-cli] Unhide workflow commands (#2683)
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->

# Why

Going to release soon.

# How

Removed `hidden = true` overrides.

# Test Plan

`easd --help` printed out information about workflow commands.

```
~/Developer/test-local (main [$!]) easd --help
EAS command line tool

VERSION
  eas-cli/13.1.1 darwin-arm64 node-v22.4.0

USAGE
  $ eas [COMMAND]

TOPICS
...
  workflow     manage workflows
```

```
~/Developer/test-local (main [$!]) easd workflow --help                       
manage workflows

USAGE
  $ eas workflow:COMMAND

COMMANDS
  workflow:run       Run an EAS workflow
  workflow:validate  validate a workflow configuration yaml file
```
2024-11-18 19:28:49 +01:00
Stanisław Chmiela 7fc09b2376 [eas-cli] Improve workflow:run and workflow:validate (#2700)
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->

# Why

- running workflows requires GitHub connection
- workflow config may be a valid YAML, but invalid config

We want to check both of these:
- in `workflow:validate`
- before we upload project sources to GCS in `workflow:run`.

# How

I added a `validateWorkflowRevisionYamlConfig` mutation I'm using here to validate the config _and_ GitHub connection. The GitHub requirement is checked dynamically in `www` so we can later remove it without having users upgrade to a newer `eas-cli`.

Brent also wished `eas workflow:run test.yml` resolved `test.yml` to `.eas/workflows/test.yml` automatically, so added this too.

# Test Plan

I tried validating and running invalid YAMLs, workflows and valid configs. Things seemed to work ok.
2024-11-18 19:26:45 +01:00
Expo CI fed28a87be update CHANGELOG.md 2024-11-15 11:03:36 +00:00
13 changed files with 1020 additions and 242 deletions

No files matched your search

+4
View File
@@ -8,10 +8,14 @@ This is the log of notable changes to EAS CLI and related packages.
### 🎉 New features
- Added `eas workflow` commands. [#2650](https://github.com/expo/eas-cli/pull/2650), [#2669](https://github.com/expo/eas-cli/pull/2669), [#2678](https://github.com/expo/eas-cli/pull/2678) by [@jonsamp](https://github.com/jonsamp) and [@sjchmiela](https://github.com/sjchmiela) ([#2683](https://github.com/expo/eas-cli/pull/2683) by [@sjchmiela](https://github.com/sjchmiela))
### 🐛 Bug fixes
### 🧹 Chores
## [13.2.3](https://github.com/expo/eas-cli/releases/tag/v13.2.3) - 2024-11-15
## [13.2.2](https://github.com/expo/eas-cli/releases/tag/v13.2.2) - 2024-11-15
## [13.2.1](https://github.com/expo/eas-cli/releases/tag/v13.2.1) - 2024-11-14
+1 -1
View File
@@ -1,5 +1,5 @@
{
"npmClient": "yarn",
"version": "13.2.3",
"version": "13.3.0",
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
}
+126 -63
View File
@@ -127,6 +127,9 @@ eas --help COMMAND
* [`eas webhook:update`](#eas-webhookupdate)
* [`eas webhook:view ID`](#eas-webhookview-id)
* [`eas whoami`](#eas-whoami)
* [`eas workflow:create [NAME]`](#eas-workflowcreate-name)
* [`eas workflow:run [FILE]`](#eas-workflowrun-file)
* [`eas workflow:validate PATH`](#eas-workflowvalidate-path)
## `eas account:login`
@@ -146,7 +149,7 @@ ALIASES
$ eas login
```
_See code: [packages/eas-cli/src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/account/login.ts)_
## `eas account:logout`
@@ -163,7 +166,7 @@ ALIASES
$ eas logout
```
_See code: [packages/eas-cli/src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/account/logout.ts)_
## `eas account:view`
@@ -180,7 +183,7 @@ ALIASES
$ eas whoami
```
_See code: [packages/eas-cli/src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/account/view.ts)_
## `eas analytics [STATUS]`
@@ -194,7 +197,7 @@ DESCRIPTION
display or change analytics settings
```
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v13.2.3/packages/eas-cli/src/commands/analytics.ts)_
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v13.3.0/packages/eas-cli/src/commands/analytics.ts)_
## `eas autocomplete [SHELL]`
@@ -246,7 +249,7 @@ DESCRIPTION
create a branch
```
_See code: [packages/eas-cli/src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/branch/create.ts)_
## `eas branch:delete [NAME]`
@@ -267,7 +270,7 @@ DESCRIPTION
delete a branch
```
_See code: [packages/eas-cli/src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/branch/delete.ts)_
## `eas branch:list`
@@ -287,7 +290,7 @@ DESCRIPTION
list all branches
```
_See code: [packages/eas-cli/src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/branch/list.ts)_
## `eas branch:rename`
@@ -307,7 +310,7 @@ DESCRIPTION
rename a branch
```
_See code: [packages/eas-cli/src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/branch/rename.ts)_
## `eas branch:view [NAME]`
@@ -330,7 +333,7 @@ DESCRIPTION
view a branch
```
_See code: [packages/eas-cli/src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/branch/view.ts)_
## `eas build`
@@ -367,7 +370,7 @@ DESCRIPTION
start a build
```
_See code: [packages/eas-cli/src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/build/index.ts)_
## `eas build:cancel [BUILD_ID]`
@@ -386,7 +389,7 @@ DESCRIPTION
cancel a build
```
_See code: [packages/eas-cli/src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/build/cancel.ts)_
## `eas build:configure`
@@ -403,7 +406,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/build/configure.ts)_
## `eas build:delete [BUILD_ID]`
@@ -422,7 +425,7 @@ DESCRIPTION
delete a build
```
_See code: [packages/eas-cli/src/commands/build/delete.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/build/delete.ts)_
## `eas build:inspect`
@@ -457,7 +460,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/build/inspect.ts)_
## `eas build:list`
@@ -507,7 +510,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/build/list.ts)_
## `eas build:resign`
@@ -536,7 +539,7 @@ DESCRIPTION
re-sign a build archive
```
_See code: [packages/eas-cli/src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/build/resign.ts)_
## `eas build:run`
@@ -562,7 +565,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/build/run.ts)_
## `eas build:submit`
@@ -612,7 +615,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/build/version/get.ts)_
## `eas build:version:set`
@@ -631,7 +634,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/build/version/set.ts)_
## `eas build:version:sync`
@@ -650,7 +653,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/build/version/sync.ts)_
## `eas build:view [BUILD_ID]`
@@ -667,7 +670,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/build/view.ts)_
## `eas channel:create [NAME]`
@@ -688,7 +691,7 @@ DESCRIPTION
create a channel
```
_See code: [packages/eas-cli/src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/channel/create.ts)_
## `eas channel:edit [NAME]`
@@ -710,7 +713,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/channel/edit.ts)_
## `eas channel:list`
@@ -730,7 +733,7 @@ DESCRIPTION
list all channels
```
_See code: [packages/eas-cli/src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/channel/list.ts)_
## `eas channel:pause [NAME]`
@@ -752,7 +755,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/channel/pause.ts)_
## `eas channel:resume [NAME]`
@@ -774,7 +777,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/channel/resume.ts)_
## `eas channel:rollout [CHANNEL]`
@@ -807,7 +810,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/channel/rollout.ts)_
## `eas channel:view [NAME]`
@@ -830,7 +833,7 @@ DESCRIPTION
view a channel
```
_See code: [packages/eas-cli/src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/channel/view.ts)_
## `eas config`
@@ -851,7 +854,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/v13.2.3/packages/eas-cli/src/commands/config.ts)_
_See code: [packages/eas-cli/src/commands/config.ts](https://github.com/expo/eas-cli/blob/v13.3.0/packages/eas-cli/src/commands/config.ts)_
## `eas credentials`
@@ -868,7 +871,7 @@ DESCRIPTION
manage credentials
```
_See code: [packages/eas-cli/src/commands/credentials/index.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/credentials/index.ts)_
## `eas credentials:configure-build`
@@ -886,7 +889,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/credentials/configure-build.ts)_
## `eas device:create`
@@ -900,7 +903,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/device/create.ts)_
## `eas device:delete`
@@ -920,7 +923,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/device/delete.ts)_
## `eas device:list`
@@ -941,7 +944,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/device/list.ts)_
## `eas device:rename`
@@ -962,7 +965,7 @@ DESCRIPTION
rename a registered device
```
_See code: [packages/eas-cli/src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/device/rename.ts)_
## `eas device:view [UDID]`
@@ -976,7 +979,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/device/view.ts)_
## `eas diagnostics`
@@ -990,7 +993,7 @@ DESCRIPTION
display environment info
```
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v13.2.3/packages/eas-cli/src/commands/diagnostics.ts)_
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v13.3.0/packages/eas-cli/src/commands/diagnostics.ts)_
## `eas help [COMMAND]`
@@ -1098,7 +1101,7 @@ DESCRIPTION
validate the local store configuration
```
_See code: [packages/eas-cli/src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/metadata/lint.ts)_
## `eas metadata:pull`
@@ -1115,7 +1118,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/metadata/pull.ts)_
## `eas metadata:push`
@@ -1132,7 +1135,7 @@ DESCRIPTION
sync the local store configuration to the app stores
```
_See code: [packages/eas-cli/src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/metadata/push.ts)_
## `eas onboarding [TARGET_PROJECT_DIRECTORY]`
@@ -1162,7 +1165,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/v13.2.3/packages/eas-cli/src/commands/open.ts)_
_See code: [packages/eas-cli/src/commands/open.ts](https://github.com/expo/eas-cli/blob/v13.3.0/packages/eas-cli/src/commands/open.ts)_
## `eas project:info`
@@ -1176,7 +1179,7 @@ DESCRIPTION
information about the current project
```
_See code: [packages/eas-cli/src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/project/info.ts)_
## `eas project:init`
@@ -1199,7 +1202,7 @@ ALIASES
$ eas init
```
_See code: [packages/eas-cli/src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/project/init.ts)_
## `eas project:onboarding [TARGET_PROJECT_DIRECTORY]`
@@ -1217,7 +1220,7 @@ ALIASES
$ eas onboarding
```
_See code: [packages/eas-cli/src/commands/project/onboarding.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/project/onboarding.ts)_
## `eas secret:create`
@@ -1240,7 +1243,7 @@ DESCRIPTION
create an environment secret on the current project or owner account
```
_See code: [packages/eas-cli/src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v13.2.3/packages/eas-cli/src/commands/secret/create.ts)_
_See code: [packages/eas-cli/src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v13.3.0/packages/eas-cli/src/commands/secret/create.ts)_
## `eas secret:delete`
@@ -1258,7 +1261,7 @@ DESCRIPTION
delete an environment secret by ID
```
_See code: [packages/eas-cli/src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v13.2.3/packages/eas-cli/src/commands/secret/delete.ts)_
_See code: [packages/eas-cli/src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v13.3.0/packages/eas-cli/src/commands/secret/delete.ts)_
## `eas secret:list`
@@ -1272,7 +1275,7 @@ DESCRIPTION
list environment secrets available for your current app
```
_See code: [packages/eas-cli/src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v13.2.3/packages/eas-cli/src/commands/secret/list.ts)_
_See code: [packages/eas-cli/src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v13.3.0/packages/eas-cli/src/commands/secret/list.ts)_
## `eas secret:push`
@@ -1292,7 +1295,7 @@ DESCRIPTION
read environment secrets from env file and store on the server
```
_See code: [packages/eas-cli/src/commands/secret/push.ts](https://github.com/expo/eas-cli/blob/v13.2.3/packages/eas-cli/src/commands/secret/push.ts)_
_See code: [packages/eas-cli/src/commands/secret/push.ts](https://github.com/expo/eas-cli/blob/v13.3.0/packages/eas-cli/src/commands/secret/push.ts)_
## `eas submit`
@@ -1323,7 +1326,7 @@ ALIASES
$ eas build:submit
```
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v13.2.3/packages/eas-cli/src/commands/submit.ts)_
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v13.3.0/packages/eas-cli/src/commands/submit.ts)_
## `eas update`
@@ -1361,7 +1364,7 @@ DESCRIPTION
publish an update group
```
_See code: [packages/eas-cli/src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/update/index.ts)_
## `eas update:configure`
@@ -1379,7 +1382,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/update/configure.ts)_
## `eas update:delete GROUPID`
@@ -1400,7 +1403,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/update/delete.ts)_
## `eas update:edit [GROUPID]`
@@ -1424,7 +1427,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/update/edit.ts)_
## `eas update:list`
@@ -1446,7 +1449,7 @@ DESCRIPTION
view the recent updates
```
_See code: [packages/eas-cli/src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/update/list.ts)_
## `eas update:republish`
@@ -1478,7 +1481,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/update/republish.ts)_
## `eas update:roll-back-to-embedded`
@@ -1506,7 +1509,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/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/update/roll-back-to-embedded.ts)_
## `eas update:rollback`
@@ -1526,7 +1529,7 @@ DESCRIPTION
roll back to an embedded update or an existing update
```
_See code: [packages/eas-cli/src/commands/update/rollback.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/update/rollback.ts)_
## `eas update:view GROUPID`
@@ -1546,7 +1549,7 @@ DESCRIPTION
update group details
```
_See code: [packages/eas-cli/src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/update/view.ts)_
## `eas webhook:create`
@@ -1567,7 +1570,7 @@ DESCRIPTION
create a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/webhook/create.ts)_
## `eas webhook:delete [ID]`
@@ -1587,7 +1590,7 @@ DESCRIPTION
delete a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/webhook/delete.ts)_
## `eas webhook:list`
@@ -1605,7 +1608,7 @@ DESCRIPTION
list webhooks
```
_See code: [packages/eas-cli/src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/webhook/list.ts)_
## `eas webhook:update`
@@ -1627,7 +1630,7 @@ DESCRIPTION
update a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/webhook/update.ts)_
## `eas webhook:view ID`
@@ -1644,7 +1647,7 @@ DESCRIPTION
view a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v13.2.3/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/v13.3.0/packages/eas-cli/src/commands/webhook/view.ts)_
## `eas whoami`
@@ -1660,4 +1663,64 @@ DESCRIPTION
ALIASES
$ eas whoami
```
## `eas workflow:create [NAME]`
create a new workflow configuration YAML file
```
USAGE
$ eas workflow:create [NAME] [--non-interactive]
ARGUMENTS
NAME Name of the workflow file (must end with .yml or .yaml)
FLAGS
--non-interactive Run the command in non-interactive mode.
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/v13.3.0/packages/eas-cli/src/commands/workflow/create.ts)_
## `eas workflow:run [FILE]`
Run an EAS workflow
```
USAGE
$ eas workflow:run [FILE] [--non-interactive]
ARGUMENTS
FILE Path to the workflow file to run
FLAGS
--non-interactive Run the command in non-interactive mode.
DESCRIPTION
Run an EAS workflow
```
_See code: [packages/eas-cli/src/commands/workflow/run.ts](https://github.com/expo/eas-cli/blob/v13.3.0/packages/eas-cli/src/commands/workflow/run.ts)_
## `eas workflow:validate PATH`
validate a workflow configuration yaml file
```
USAGE
$ eas workflow:validate PATH [--non-interactive]
ARGUMENTS
PATH Path to the workflow configuration YAML file (must end with .yml or .yaml)
FLAGS
--non-interactive Run the command in non-interactive mode.
DESCRIPTION
validate a workflow configuration yaml file
```
_See code: [packages/eas-cli/src/commands/workflow/validate.ts](https://github.com/expo/eas-cli/blob/v13.3.0/packages/eas-cli/src/commands/workflow/validate.ts)_
<!-- commandsstop -->
+471 -1
View File
@@ -4610,6 +4610,11 @@
"kind": "OBJECT",
"name": "WorkerDeployment",
"ofType": null
},
{
"kind": "OBJECT",
"name": "WorkflowRun",
"ofType": null
}
]
},
@@ -4644,6 +4649,12 @@
"description": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "WORKFLOW_RUN",
"description": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"possibleTypes": null
@@ -28471,6 +28482,199 @@
],
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "Fingerprint",
"description": null,
"fields": [
{
"name": "app",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "App",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "createdAt",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "DateTime",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "debugInfoUrl",
"description": null,
"args": [],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "hash",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "id",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "updatedAt",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "DateTime",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "FingerprintInfo",
"description": null,
"fields": null,
"inputFields": [
{
"name": "fingerprintHash",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "fingerprintSource",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "FingerprintSourceInput",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "FingerprintInfoGroup",
"description": null,
"fields": null,
"inputFields": [
{
"name": "android",
"description": null,
"type": {
"kind": "INPUT_OBJECT",
"name": "FingerprintInfo",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "ios",
"description": null,
"type": {
"kind": "INPUT_OBJECT",
"name": "FingerprintInfo",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "web",
"description": null,
"type": {
"kind": "INPUT_OBJECT",
"name": "FingerprintInfo",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "FingerprintSourceInput",
@@ -34395,6 +34599,30 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "errors",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "JobRunError",
"ofType": null
}
}
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "expiresAt",
"description": null,
@@ -34613,6 +34841,73 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "JobRunError",
"description": null,
"fields": [
{
"name": "buildPhase",
"description": null,
"args": [],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "docsUrl",
"description": null,
"args": [],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "errorCode",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "message",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "JobRunMutation",
@@ -37809,6 +38104,18 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "fingerprintInfoGroup",
"description": null,
"type": {
"kind": "INPUT_OBJECT",
"name": "FingerprintInfoGroup",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "gitCommitHash",
"description": null,
@@ -39850,6 +40157,22 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "workflowRevision",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "WorkflowRevisionMutation",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "workflowRun",
"description": null,
@@ -45259,6 +45582,18 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "fingerprint",
"description": null,
"args": [],
"type": {
"kind": "OBJECT",
"name": "Fingerprint",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "gitCommitHash",
"description": null,
@@ -52996,6 +53331,18 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "tier",
"description": null,
"args": [],
"type": {
"kind": "ENUM",
"name": "WorkerDeploymentTier",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "url",
"description": null,
@@ -56279,6 +56626,29 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "ENUM",
"name": "WorkerDeploymentTier",
"description": null,
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": [
{
"name": "FREE",
"description": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "PAID",
"description": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "WorkerDeploymentsConnection",
@@ -57071,6 +57441,12 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "GET_BUILD",
"description": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "MAESTRO_TEST",
"description": null,
@@ -57407,6 +57783,66 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "WorkflowRevisionMutation",
"description": null,
"fields": [
{
"name": "validateWorkflowYamlConfig",
"description": null,
"args": [
{
"name": "appId",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "yamlConfig",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "WorkflowRevisionQuery",
@@ -57507,6 +57943,34 @@
"name": "WorkflowRun",
"description": null,
"fields": [
{
"name": "activityTimestamp",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "DateTime",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "actor",
"description": null,
"args": [],
"type": {
"kind": "INTERFACE",
"name": "Actor",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "createdAt",
"description": null,
@@ -57713,7 +58177,13 @@
}
],
"inputFields": null,
"interfaces": [],
"interfaces": [
{
"kind": "INTERFACE",
"name": "ActivityTimelineProjectActivity",
"ofType": null
}
],
"enumValues": null,
"possibleTypes": null
},
+4 -1
View File
@@ -1,7 +1,7 @@
{
"name": "eas-cli",
"description": "EAS command line tool",
"version": "13.2.3",
"version": "13.3.0",
"author": "Expo <[email protected]>",
"bin": {
"eas": "./bin/run"
@@ -182,6 +182,9 @@
},
"webhook": {
"description": "manage webhooks"
},
"workflow": {
"description": "manage workflows"
}
},
"warn-if-update-available": {
+9
View File
@@ -63,3 +63,12 @@ export function getWorkflowRunUrl(
getExpoWebsiteBaseUrl()
).toString();
}
export function getProjectGitHubSettingsUrl(accountName: string, projectName: string): string {
return new URL(
`/accounts/${encodeURIComponent(accountName)}/projects/${encodeURIComponent(
projectName
)}/github`,
getExpoWebsiteBaseUrl()
).toString();
}
@@ -0,0 +1,121 @@
import chalk from 'chalk';
import fs from 'fs/promises';
import fsExtra from 'fs-extra';
import path from 'path';
import prompts from 'prompts';
import EasCommand from '../../commandUtils/EasCommand';
import { EASNonInteractiveFlag } from '../../commandUtils/flags';
import Log from '../../log';
import { WorkflowFile } from '../../utils/workflowFile';
const DEFAULT_WORKFLOW_NAME = 'workflow.yml';
const HELLO_WORLD_TEMPLATE = `name: Hello World
on:
push:
branches: ['*']
jobs:
hello_world:
steps:
- uses: eas/checkout
- run: echo "Hello, World"
`;
export class WorkflowCreate extends EasCommand {
static override description = 'create a new workflow configuration YAML file';
static override args = [
{
name: 'name',
description: 'Name of the workflow file (must end with .yml or .yaml)',
required: false,
},
];
static override flags = {
...EASNonInteractiveFlag,
};
static override contextDefinition = {
...this.ContextOptions.ProjectDir,
};
async runAsync(): Promise<void> {
const {
args: { name: argFileName },
flags,
} = await this.parse(WorkflowCreate);
const { projectDir } = await this.getContextAsync(WorkflowCreate, {
nonInteractive: flags['non-interactive'],
});
let fileName = argFileName;
if (!fileName) {
const response = await prompts({
type: 'text',
name: 'fileName',
message: 'What would you like to name your workflow file?',
initial: DEFAULT_WORKFLOW_NAME,
validate: value => {
try {
WorkflowFile.validateYamlExtension(value);
return true;
} catch (error) {
return error instanceof Error ? error.message : 'Invalid file name';
}
},
});
if (!response.fileName) {
Log.warn('Workflow creation cancelled.');
process.exit(0);
}
fileName = response.fileName;
}
try {
await this.ensureWorkflowsDirectoryExistsAsync({ projectDir });
await this.createWorkflowFileAsync({ fileName, projectDir });
} catch (error) {
Log.error('Failed to create workflow file.');
throw error;
}
}
private async ensureWorkflowsDirectoryExistsAsync({
projectDir,
}: {
projectDir: string;
}): Promise<void> {
try {
await fs.access(path.join(projectDir, '.eas', 'workflows'));
} catch {
await fs.mkdir(path.join(projectDir, '.eas', 'workflows'), { recursive: true });
Log.withTick(`Created directory ${chalk.bold(path.join(projectDir, '.eas', 'workflows'))}`);
}
}
private async createWorkflowFileAsync({
fileName,
projectDir,
}: {
fileName: string;
projectDir: string;
}): Promise<void> {
WorkflowFile.validateYamlExtension(fileName);
const filePath = path.join(projectDir, '.eas', 'workflows', fileName);
if (await fsExtra.pathExists(filePath)) {
throw new Error(`Workflow file already exists: ${filePath}`);
}
await fs.writeFile(filePath, HELLO_WORLD_TEMPLATE);
Log.withTick(`Created ${chalk.bold(filePath)}`);
}
}
+26 -8
View File
@@ -1,23 +1,21 @@
import fs from 'node:fs';
import { CombinedError } from '@urql/core';
import * as path from 'node:path';
import { getWorkflowRunUrl } from '../../build/utils/url';
import EasCommand from '../../commandUtils/EasCommand';
import { EASNonInteractiveFlag } from '../../commandUtils/flags';
import { WorkflowProjectSourceType } from '../../graphql/generated';
import { WorkflowRevisionMutation } from '../../graphql/mutations/WorkflowRevisionMutation';
import { WorkflowRunMutation } from '../../graphql/mutations/WorkflowRunMutation';
import Log, { link } from '../../log';
import { getOwnerAccountForProjectIdAsync } from '../../project/projectUtils';
import { uploadAccountScopedEasJsonAsync } from '../../project/uploadAccountScopedEasJsonAsync';
import { uploadAccountScopedProjectSourceAsync } from '../../project/uploadAccountScopedProjectSourceAsync';
import { WorkflowFile } from '../../utils/workflowFile';
export default class WorkflowRun extends EasCommand {
static override description = 'Run an EAS workflow';
// TODO(@sjchmiela): Keep command hidden until workflows are live
static override hidden = true;
static override state = 'beta';
static override args = [{ name: 'file', description: 'Path to the workflow file to run' }];
static override flags = {
@@ -34,8 +32,6 @@ export default class WorkflowRun extends EasCommand {
async runAsync(): Promise<void> {
const { flags, args } = await this.parse(WorkflowRun);
Log.warn('Workflows are in beta and subject to breaking changes.');
const {
getDynamicPrivateProjectConfigAsync,
loggedIn: { graphqlClient },
@@ -48,7 +44,12 @@ export default class WorkflowRun extends EasCommand {
let yamlConfig: string;
try {
yamlConfig = await fs.promises.readFile(path.join(projectDir, args.file), 'utf8');
const workflowFileContents = await WorkflowFile.readWorkflowFileContentsAsync({
projectDir,
filePath: args.file,
});
Log.log(`Using workflow file from ${workflowFileContents.filePath}`);
yamlConfig = workflowFileContents.yamlConfig;
} catch (err) {
Log.error('Failed to read workflow file.');
@@ -61,6 +62,23 @@ export default class WorkflowRun extends EasCommand {
} = await getDynamicPrivateProjectConfigAsync();
const account = await getOwnerAccountForProjectIdAsync(graphqlClient, projectId);
try {
await WorkflowRevisionMutation.validateWorkflowYamlConfigAsync(graphqlClient, {
appId: projectId,
yamlConfig,
});
} catch (error) {
if (error instanceof CombinedError) {
WorkflowFile.maybePrintWorkflowFileValidationErrors({
error,
accountName: account.name,
projectName,
});
throw error;
}
}
let projectArchiveBucketKey: string;
let easJsonBucketKey: string;
@@ -1,14 +1,16 @@
import fs from 'fs/promises';
import path from 'path';
import { CombinedError } from '@urql/core';
import * as YAML from 'yaml';
import EasCommand from '../../commandUtils/EasCommand';
import { EASNonInteractiveFlag } from '../../commandUtils/flags';
import { WorkflowRevisionMutation } from '../../graphql/mutations/WorkflowRevisionMutation';
import Log from '../../log';
import { ora } from '../../ora';
import { getOwnerAccountForProjectIdAsync } from '../../project/projectUtils';
import { WorkflowFile } from '../../utils/workflowFile';
export class WorkflowValidate extends EasCommand {
static override description = 'validate a workflow configuration yaml file';
static override hidden = true;
static override args = [
{
@@ -18,81 +20,83 @@ export class WorkflowValidate extends EasCommand {
},
];
static override flags = {
...EASNonInteractiveFlag,
};
static override contextDefinition = {
...this.ContextOptions.DynamicProjectConfig,
...this.ContextOptions.ProjectDir,
...this.ContextOptions.LoggedIn,
};
async runAsync(): Promise<void> {
const {
args: { path: filePath },
flags,
} = await this.parse(WorkflowValidate);
const {
getDynamicPrivateProjectConfigAsync,
loggedIn: { graphqlClient },
projectDir,
} = await this.getContextAsync(WorkflowValidate, {
nonInteractive: flags['non-interactive'],
withServerSideEnvironment: null,
});
const {
projectId,
exp: { slug: projectName },
} = await getDynamicPrivateProjectConfigAsync();
const account = await getOwnerAccountForProjectIdAsync(graphqlClient, projectId);
const spinner = ora().start('Validating the workflow YAML file…');
try {
await validateYAMLAsync(filePath);
const workflowFileContents = await WorkflowFile.readWorkflowFileContentsAsync({
projectDir,
filePath,
});
Log.log(`Using workflow file from ${workflowFileContents.filePath}`);
const parsedYaml = YAML.parse(workflowFileContents.yamlConfig);
// Check if the parsed result is empty or null
if (
parsedYaml === null ||
parsedYaml === undefined ||
(typeof parsedYaml === 'object' && Object.keys(parsedYaml).length === 0)
) {
throw new Error('YAML file is empty or contains only comments.');
}
await WorkflowRevisionMutation.validateWorkflowYamlConfigAsync(graphqlClient, {
appId: projectId,
yamlConfig: workflowFileContents.yamlConfig,
});
spinner.succeed('Workflow configuration YAML is valid.');
} catch (error) {
spinner.fail('Workflow configuration YAML is not valid.');
if (error instanceof YAML.YAMLParseError) {
Log.error(`YAML syntax error: ${error.message}`);
} else if (error instanceof CombinedError) {
WorkflowFile.maybePrintWorkflowFileValidationErrors({
error,
accountName: account.name,
projectName,
});
throw error;
} else if (error instanceof Error) {
Log.error(error.message);
} else {
Log.error(`Unexpected error: ${String(error)}`);
}
process.exit(1);
}
}
}
async function checkIfFileExistsAsync(filePath: string): Promise<void> {
try {
await fs.access(filePath);
} catch {
throw new Error(`File does not exist: ${filePath}`);
}
}
function checkIfValidYAMLFileExtension(filePath: string): void {
const fileExtension = path.extname(filePath).toLowerCase();
if (fileExtension !== '.yml' && fileExtension !== '.yaml') {
throw new Error('File must have a .yml or .yaml extension');
}
}
async function validateYAMLAsync(filePath: string): Promise<void> {
await checkIfFileExistsAsync(filePath);
checkIfValidYAMLFileExtension(filePath);
try {
const fileContents = await fs.readFile(filePath, 'utf8');
// First check if the file is empty or only contains whitespace
if (!fileContents.trim()) {
throw new Error('YAML file is empty or contains only comments.');
}
const parsedYaml = YAML.parse(fileContents);
// Check if the parsed result is empty or null
if (
parsedYaml === null ||
parsedYaml === undefined ||
(typeof parsedYaml === 'object' && Object.keys(parsedYaml).length === 0)
) {
throw new Error('YAML file is empty or contains only comments.');
}
} catch (error) {
if (
error instanceof Error &&
error.message === 'YAML file is empty or contains only comments.'
) {
throw error;
}
if (error instanceof YAML.YAMLParseError || error instanceof Error) {
throw new Error(`YAML parsing error: ${error.message}`);
} else {
throw new Error(`YAML parsing error: ${String(error)}`);
}
}
}
+64 -2
View File
@@ -767,7 +767,8 @@ export enum ActivityTimelineProjectActivityType {
Build = 'BUILD',
Submission = 'SUBMISSION',
Update = 'UPDATE',
Worker = 'WORKER'
Worker = 'WORKER',
WorkflowRun = 'WORKFLOW_RUN'
}
/** A regular user, SSO user, or robot that can authenticate with Expo services and be a member of accounts. */
@@ -4179,6 +4180,27 @@ export enum Feature {
Teams = 'TEAMS'
}
export type Fingerprint = {
__typename?: 'Fingerprint';
app: App;
createdAt: Scalars['DateTime']['output'];
debugInfoUrl?: Maybe<Scalars['String']['output']>;
hash: Scalars['String']['output'];
id: Scalars['ID']['output'];
updatedAt: Scalars['DateTime']['output'];
};
export type FingerprintInfo = {
fingerprintHash: Scalars['String']['input'];
fingerprintSource: FingerprintSourceInput;
};
export type FingerprintInfoGroup = {
android?: InputMaybe<FingerprintInfo>;
ios?: InputMaybe<FingerprintInfo>;
web?: InputMaybe<FingerprintInfo>;
};
export type FingerprintSourceInput = {
bucketKey?: InputMaybe<Scalars['String']['input']>;
isDebugFingerprint?: InputMaybe<Scalars['Boolean']['input']>;
@@ -4975,6 +4997,7 @@ export type JobRun = {
createdAt: Scalars['DateTime']['output'];
displayName?: Maybe<Scalars['String']['output']>;
endedAt?: Maybe<Scalars['DateTime']['output']>;
errors: Array<JobRunError>;
expiresAt: Scalars['DateTime']['output'];
gitCommitHash?: Maybe<Scalars['String']['output']>;
gitCommitMessage?: Maybe<Scalars['String']['output']>;
@@ -4990,6 +5013,14 @@ export type JobRun = {
updateGroups: Array<Array<Update>>;
};
export type JobRunError = {
__typename?: 'JobRunError';
buildPhase?: Maybe<Scalars['String']['output']>;
docsUrl?: Maybe<Scalars['String']['output']>;
errorCode: Scalars['String']['output'];
message: Scalars['String']['output'];
};
export type JobRunMutation = {
__typename?: 'JobRunMutation';
/** Cancel an EAS Job Run */
@@ -5477,6 +5508,7 @@ export type PublishUpdateGroupInput = {
awaitingCodeSigningInfo?: InputMaybe<Scalars['Boolean']['input']>;
branchId: Scalars['String']['input'];
excludedAssets?: InputMaybe<Array<PartialManifestAsset>>;
fingerprintInfoGroup?: InputMaybe<FingerprintInfoGroup>;
gitCommitHash?: InputMaybe<Scalars['String']['input']>;
isGitWorkingTreeDirty?: InputMaybe<Scalars['Boolean']['input']>;
message?: InputMaybe<Scalars['String']['input']>;
@@ -5739,6 +5771,7 @@ export type RootMutation = {
/** Mutations that modify a websiteNotification */
websiteNotifications: WebsiteNotificationMutation;
workflowJob: WorkflowJobMutation;
workflowRevision: WorkflowRevisionMutation;
workflowRun: WorkflowRunMutation;
};
@@ -6535,6 +6568,7 @@ export type Update = ActivityTimelineProjectActivity & {
createdAt: Scalars['DateTime']['output'];
deployments: DeploymentResult;
expoGoSDKVersion?: Maybe<Scalars['String']['output']>;
fingerprint?: Maybe<Fingerprint>;
gitCommitHash?: Maybe<Scalars['String']['output']>;
group: Scalars['String']['output'];
id: Scalars['ID']['output'];
@@ -7627,6 +7661,7 @@ export type WorkerDeployment = ActivityTimelineProjectActivity & {
logs?: Maybe<WorkerDeploymentLogs>;
requests?: Maybe<WorkerDeploymentRequests>;
subdomain: Scalars['String']['output'];
tier?: Maybe<WorkerDeploymentTier>;
url: Scalars['String']['output'];
};
@@ -7979,6 +8014,11 @@ export type WorkerDeploymentRequestsTimeseriesEdge = {
timestamp: Scalars['DateTime']['output'];
};
export enum WorkerDeploymentTier {
Free = 'FREE',
Paid = 'PAID'
}
export type WorkerDeploymentsConnection = {
__typename?: 'WorkerDeploymentsConnection';
edges: Array<WorkerDeploymentEdge>;
@@ -8081,6 +8121,7 @@ export enum WorkflowJobType {
AppleDeviceRegistrationRequest = 'APPLE_DEVICE_REGISTRATION_REQUEST',
Build = 'BUILD',
Custom = 'CUSTOM',
GetBuild = 'GET_BUILD',
MaestroTest = 'MAESTRO_TEST',
RequireApproval = 'REQUIRE_APPROVAL',
Submission = 'SUBMISSION',
@@ -8130,6 +8171,17 @@ export type WorkflowRevisionInput = {
yamlConfig: Scalars['String']['input'];
};
export type WorkflowRevisionMutation = {
__typename?: 'WorkflowRevisionMutation';
validateWorkflowYamlConfig: Scalars['Boolean']['output'];
};
export type WorkflowRevisionMutationValidateWorkflowYamlConfigArgs = {
appId: Scalars['ID']['input'];
yamlConfig: Scalars['String']['input'];
};
export type WorkflowRevisionQuery = {
__typename?: 'WorkflowRevisionQuery';
byId: WorkflowRevision;
@@ -8146,8 +8198,10 @@ export type WorkflowRevisionsConnection = {
pageInfo: PageInfo;
};
export type WorkflowRun = {
export type WorkflowRun = ActivityTimelineProjectActivity & {
__typename?: 'WorkflowRun';
activityTimestamp: Scalars['DateTime']['output'];
actor?: Maybe<Actor>;
createdAt: Scalars['DateTime']['output'];
gitCommitHash?: Maybe<Scalars['String']['output']>;
gitCommitMessage?: Maybe<Scalars['String']['output']>;
@@ -8967,6 +9021,14 @@ export type DeleteWebhookMutationVariables = Exact<{
export type DeleteWebhookMutation = { __typename?: 'RootMutation', webhook: { __typename?: 'WebhookMutation', deleteWebhook: { __typename?: 'DeleteWebhookResult', id: string } } };
export type ValidateWorkflowYamlConfigMutationVariables = Exact<{
appId: Scalars['ID']['input'];
yamlConfig: Scalars['String']['input'];
}>;
export type ValidateWorkflowYamlConfigMutation = { __typename?: 'RootMutation', workflowRevision: { __typename?: 'WorkflowRevisionMutation', validateWorkflowYamlConfig: boolean } };
export type CreateWorkflowRunMutationVariables = Exact<{
appId: Scalars['ID']['input'];
workflowRevisionInput: WorkflowRevisionInput;
@@ -0,0 +1,48 @@
import gql from 'graphql-tag';
import { z } from 'zod';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { withErrorHandlingAsync } from '../client';
import {
ValidateWorkflowYamlConfigMutation,
ValidateWorkflowYamlConfigMutationVariables,
} from '../generated';
export namespace WorkflowRevisionMutation {
export const ValidationErrorExtensionZ = z.object({
errorCode: z.literal('VALIDATION_ERROR'),
metadata: z.object({
formErrors: z.array(z.string()),
fieldErrors: z.record(z.string(), z.array(z.string())),
}),
});
export async function validateWorkflowYamlConfigAsync(
graphqlClient: ExpoGraphqlClient,
{
appId,
yamlConfig,
}: {
appId: string;
yamlConfig: string;
}
): Promise<void> {
await withErrorHandlingAsync(
graphqlClient
.mutation<ValidateWorkflowYamlConfigMutation, ValidateWorkflowYamlConfigMutationVariables>(
gql`
mutation ValidateWorkflowYamlConfig($appId: ID!, $yamlConfig: String!) {
workflowRevision {
validateWorkflowYamlConfig(appId: $appId, yamlConfig: $yamlConfig)
}
}
`,
{
appId,
yamlConfig,
}
)
.toPromise()
);
}
}
@@ -0,0 +1,85 @@
import { CombinedError } from '@urql/core';
import fs from 'fs';
import path from 'path';
import { getProjectGitHubSettingsUrl } from '../build/utils/url';
import { WorkflowRevisionMutation } from '../graphql/mutations/WorkflowRevisionMutation';
import Log, { link } from '../log';
export namespace WorkflowFile {
export async function readWorkflowFileContentsAsync({
projectDir,
filePath,
}: {
projectDir: string;
filePath: string;
}): Promise<{ yamlConfig: string; filePath: string }> {
const [yamlFromEasWorkflowsFile, yamlFromFile] = await Promise.allSettled([
fs.promises.readFile(path.join(projectDir, '.eas', 'workflows', filePath), 'utf8'),
fs.promises.readFile(path.join(process.cwd(), filePath), 'utf8'),
]);
// We prioritize .eas/workflows/${file} over ${file}, because
// in the worst case we'll try to read .eas/workflows/.eas/workflows/test.yml,
// which is likely not to exist.
if (yamlFromEasWorkflowsFile.status === 'fulfilled') {
return {
yamlConfig: yamlFromEasWorkflowsFile.value,
filePath: path.join(projectDir, '.eas', 'workflows', filePath),
};
} else if (yamlFromFile.status === 'fulfilled') {
return {
yamlConfig: yamlFromFile.value,
filePath: path.join(process.cwd(), filePath),
};
}
throw yamlFromFile.reason;
}
export function maybePrintWorkflowFileValidationErrors({
error,
accountName,
projectName,
}: {
error: CombinedError;
accountName: string;
projectName: string;
}): void {
const validationErrors = error.graphQLErrors.flatMap(e => {
return WorkflowRevisionMutation.ValidationErrorExtensionZ.safeParse(e.extensions).data ?? [];
});
if (validationErrors.length > 0) {
Log.error('Workflow file is invalid. Issues:');
for (const validationError of validationErrors) {
for (const formError of validationError.metadata.formErrors) {
Log.error(`- ${formError}`);
}
for (const [field, fieldErrors] of Object.entries(validationError.metadata.fieldErrors)) {
Log.error(`- ${field}: ${fieldErrors.join(', ')}`);
}
}
}
const githubNotFoundError = error.graphQLErrors.find(
e => e.extensions.errorCode === 'GITHUB_NOT_FOUND_ERROR'
);
if (githubNotFoundError) {
Log.error(`GitHub repository not found. It is currently required to run workflows.`);
Log.error(
`Please check that the repository exists and that you have access to it. ${link(
getProjectGitHubSettingsUrl(accountName, projectName)
)}`
);
}
}
export function validateYamlExtension(fileName: string): void {
const fileExtension = path.extname(fileName).toLowerCase();
if (fileExtension !== '.yml' && fileExtension !== '.yaml') {
throw new Error('File must have a .yml or .yaml extension');
}
}
}
@@ -1,109 +0,0 @@
import fs from 'fs/promises';
import { vol } from 'memfs';
import { WorkflowValidate } from '../../commands/workflow/validate';
jest.mock('fs/promises');
jest.mock('../../log');
jest.mock('../../ora', () => ({
ora: () => ({
start: () => ({
succeed: jest.fn(),
fail: jest.fn(),
}),
}),
}));
describe('WorkflowValidate', () => {
const mockValidYaml = `
name: workflow
on: push
jobs:
build:
steps:
- run: echo "Hello"
`;
const mockInvalidYaml = `
name: workflow
on: : : : invalid
`;
let command: WorkflowValidate;
beforeEach(() => {
vol.reset();
jest.resetAllMocks();
process.exit = jest.fn(() => {
throw new Error();
});
});
describe('file validation', () => {
describe('when file exists', () => {
beforeEach(() => {
(fs.access as jest.Mock).mockResolvedValue(undefined);
});
it('validates a correct YAML file', async () => {
(fs.readFile as jest.Mock).mockResolvedValue(mockValidYaml);
command = new WorkflowValidate(['./workflow.yml'], {} as any);
await expect(command.runAsync()).resolves.not.toThrow();
});
it('accepts both .yml and .yaml extensions', async () => {
(fs.readFile as jest.Mock).mockResolvedValue(mockValidYaml);
command = new WorkflowValidate(['./workflow.yml'], {} as any);
await expect(command.runAsync()).resolves.not.toThrow();
command = new WorkflowValidate(['./workflow.yaml'], {} as any);
await expect(command.runAsync()).resolves.not.toThrow();
});
it('throws error for empty YAML file', async () => {
(fs.readFile as jest.Mock).mockResolvedValue('');
command = new WorkflowValidate(['./workflow.yml'], {} as any);
await expect(command.runAsync()).rejects.toThrow();
});
it('throws error for invalid YAML syntax', async () => {
(fs.readFile as jest.Mock).mockResolvedValue(mockInvalidYaml);
command = new WorkflowValidate(['./workflow.yml'], {} as any);
await expect(command.runAsync()).rejects.toThrow();
});
it('throws error for invalid file extension', async () => {
command = new WorkflowValidate(['./workflow.txt'], {} as any);
await expect(command.runAsync()).rejects.toThrow();
});
});
describe('when file does not exist', () => {
beforeEach(() => {
(fs.access as jest.Mock).mockRejectedValue(new Error('ENOENT'));
});
it('throws appropriate error', async () => {
command = new WorkflowValidate(['./nonexistent.yml'], {} as any);
await expect(command.runAsync()).rejects.toThrow();
});
});
});
describe('error handling', () => {
it('handles unexpected errors gracefully', async () => {
(fs.access as jest.Mock).mockResolvedValue(undefined);
(fs.readFile as jest.Mock).mockRejectedValue(new Error('Unexpected error'));
command = new WorkflowValidate(['./workflow.yml'], {} as any);
await expect(command.runAsync()).rejects.toThrow();
});
});
});