Compare commits

...
Author SHA1 Message Date
Will Schurman 5e1093607b [no-commit] Test codemention 2024-09-27 16:06:59 +00:00
Will Schurman 37a68c5237 [ci] Migrate from CODEOWNERS to codemention (#2603) 2024-09-27 09:06:46 -07:00
Will Schurman 6823e4f66c [eas-cli] Disallow republishing an update that is being rolled-out (#2602) 2024-09-27 09:05:24 -07:00
Phil Pluckthun ffa2f034f9 refactor(eas-cli): Implement updated deployment upload flow (#2601)
* Update API functions for new upload endpoint and deploy result

* Fix listWorkerFilesAsync file type

* Add call to finalize deployment

* Update CHANGELOG

* Add retries to /deploy/finalize call

* Apply lints
2024-09-27 10:36:24 +01:00
Expo CI 8243f5f0cb update CHANGELOG.md 2024-09-27 05:22:24 +00:00
Szymon Dziedzic 01676a4f88 v12.5.1 2024-09-26 22:16:28 -07:00
Szymon Dziedzic 7edc10feaf [eas-cli] add exit option to eas credentials interactive menu (#2570)
<!-- 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

https://exponent-internal.slack.com/archives/C017N0N99RA/p1726226230206999

Right now the only way to exit the `eas credentials` command is to kill the process by doing ctrl+c. Let's add an `exit` option to the interactive menu.

# How

Add exit option to menu.

# Test Plan

Test manually
2024-09-27 06:21:08 +02:00
Will Schurman fba26e6b50 [eas-cli] Add destination branch arguments to update:republish command (#2575) 2024-09-26 09:32:55 -07:00
Szymon Dziedzic 69014fe21d [eas-cli] stop using environment flag in build related commands (#2547)
<!-- 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

On Friday's meeting, we agreed that having both a flag and a field in the build profile for setting the environment might be too much. Additionally, we already have a `--profile` flag that has a `-e` alias which makes it even more confusing. We decided to delete the flag to avoid confusion and make it as straightforward as possible.

# How

Delete the `--environment` flag for build-related commands, rely only on the `environment` field in eas.json.

# Test Plan

Tests
2024-09-26 16:45:03 +02:00
Szymon Dziedzic 217a1f4fdb [eas-cli] add eas env:exec command (#2549)
<!-- 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

Add the `eas env:exec` command. This command allows you to run any arbitrary bash command with env vars from a given environment.

# How

Add `eas env:exec` command

# Test Plan

Test manually

![Screenshot 2024-09-12 at 11.23.06.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/9YRXgAETSTRMfjZ0IP35/b1f2e6d3-7a4d-415d-a6e3-5754684c6349.png)
2024-09-26 16:44:16 +02:00
Cedric van Putten 0863b9a477 refactor(eas-cli): support assigning dev domain in non interactive mode (#2595)
* refactor(eas-cli): split prompt from dev domain assignment and support it non-interactive

* docs: add changelog entry

* docs: fix changelog entry

* fix(eas-cli): use proper name in "already taken" prompt

* chore: resolve linting issue
2024-09-26 12:34:14 +02:00
Stanisław Chmiela 081a254d9b [eas-cli] Replace logsUrl with logFiles (#2598)
# Why

Almost a year ago we've migrated from using a single file for submission logs to multi-file logs, accommodating need to display logs from both the worker and the scheduler that is starting the worker VM.

Companion to https://github.com/expo/universe/pull/16873.

# How

Replaced `logsUrl` with `logFiles`, adjusted code.

# Test Plan

Logs printed

<img width="1055" alt="Zrzut ekranu 2024-09-24 o 23 06 22" src="https://github.com/user-attachments/assets/6c9a45c0-6760-4629-82e3-a79d5ef99ebe">
2024-09-25 19:13:29 +02:00
Will Schurman ba7eb7ea07 [ci] Remove blurb about changelog bot since it is still disabled (#2592) 2024-09-24 13:19:46 -07:00
Cedric van Putten f5df6e6e77 refactor(eas-cli): allow Expo Router server deployments without client directory (#2597)
* refactor(eas-cli): allow Expo Router server deployments without client directories

* docs: fix changelog entry
2024-09-24 20:03:19 +02:00
Cedric van Putten c0c27559eb refactor(eas-cli): simplify the output of eas deploy --json (#2596)
* refactor(eas-cli): simplify the `eas deploy --json` output

* docs: fix changelog entry

* refactor(eas-cli): keep aliases as array in `--json` output

* docs: fix changelog entry
2024-09-24 16:45:07 +02:00
Phil Pluckthun 2e002ad709 Fix worker asset upload error not being shown (#2579) 2024-09-24 11:17:12 +01:00
Expo CI 2e211f4904 update CHANGELOG.md 2024-09-23 15:32:31 +00:00
43 changed files with 853 additions and 347 deletions

No files matched your search

+23
View File
@@ -0,0 +1,23 @@
rules:
- patterns: ['**/*']
mentions: ['szdziedzic', 'khamilowicz', 'sjchmiela']
- patterns: ['packages/eas-cli/src/build/**']
mentions: ['szdziedzic', 'khamilowicz', 'sjchmiela']
- patterns: ['packages/eas-cli/src/commands/build/**']
mentions: ['szdziedzic', 'khamilowicz', 'sjchmiela']
- patterns: ['packages/eas-cli/src/submit/**']
mentions: ['szdziedzic', 'khamilowicz', 'sjchmiela']
- patterns: ['packages/eas-cli/src/commands/submit.ts']
mentions: ['szdziedzic', 'khamilowicz', 'sjchmiela', 'radoslawkrzemien']
- patterns: ['packages/eas-cli/src/update/**']
mentions: ['EvanBacon', 'byCedric', 'wschurman']
- patterns: ['packages/eas-cli/src/commands/update/**']
mentions: ['EvanBacon', 'byCedric', 'wschurman']
- patterns: ['packages/eas-cli/schema/**']
mentions: ['bycedric']
- patterns: ['packages/eas-cli/src/metadata/**']
mentions: ['bycedric']
- patterns: ['packages/eas-cli/src/commands/metadata/**']
mentions: ['bycedric']
- patterns: ['packages/eas-json/**']
mentions: ['szdziedzic', 'khamilowicz', 'sjchmiela']
-48
View File
@@ -1,48 +0,0 @@
name: Changelog bot
on:
issue_comment:
types: [created]
jobs:
pr-commented:
runs-on: ubuntu-latest
if: ${{ github.event.issue.pull_request && github.event.issue.user.login == github.event.comment.user.login && startsWith(github.event.comment.body, '/changelog-entry ') }}
steps:
- uses: actions/checkout@v2
with:
token: ${{ secrets.EXPO_BOT_PAT }}
- uses: actions/setup-node@v2
with:
node-version: 20
- name: Checkout Pull Request
run: gh pr checkout ${{ github.event.issue.number }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install dependencies
working-directory: ./scripts
run: yarn install --frozen-lockfile --check-files
- name: Add changelog entry
working-directory: ./scripts
run: |
PARAMS=${PR_COMMENT_BODY#/changelog-entry }
if [[ ! "$PARAMS" =~ " " ]]; then
echo "Invalid /changelog-entry command"
exit 1
fi
CATEGORY=$( cut -d ' ' -f 1 <<< "$PARAMS" | sed -e 's/^[[:space:]]*//' )
MESSAGE=$( cut -d ' ' -f 2- <<< "$PARAMS" | sed -e 's/^[[:space:]]*//' )
yarn changelog-entry "$CATEGORY" "$MESSAGE"
env:
GITHUB_PR_AUTHOR: ${{ github.event.issue.user.login }}
GITHUB_PR_NUMBER: ${{ github.event.issue.number }}
PR_COMMENT_BODY: ${{ github.event.comment.body }}
- name: Commit and push
run: |
# use the last commit author name and email
git config --global user.name "$(git --no-pager log --format=format:'%an' -n 1)"
git config --global user.email "$(git --no-pager log --format=format:'%ae' -n 1)"
git add CHANGELOG.md
git commit -m "update CHANGELOG.md"
git push
+1 -2
View File
@@ -36,6 +36,5 @@ jobs:
refresh-message-position: true
message: ${{ contains(github.event.pull_request.labels.*.name, 'no changelog') && '⏩ The changelog entry check has been skipped since the "no changelog" label is present.' || '✅ Thank you for adding the changelog entry!' }}
message-failure: |
❌ It looks like a changelog entry is missing for this PR. You have two options: you can add it manually, or you can use the changelog bot to do it for you.
🤖 To use the bot, simply comment on this PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`.
❌ It looks like a changelog entry is missing for this PR. Add it manually to CHANGELOG.md.
⏩ If this PR doesn't require a changelog entry, such as if it's an internal change that doesn't affect the user experience, you can add the "no changelog" label to the PR.
+14
View File
@@ -0,0 +1,14 @@
name: codemention
on:
pull_request_target:
types: [opened, synchronize, ready_for_review]
jobs:
codemention:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: tobyhs/[email protected]
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
+26 -2
View File
@@ -8,15 +8,39 @@ This is the log of notable changes to EAS CLI and related packages.
### 🎉 New features
### 🐛 Bug fixes
- Disallow republishing an update that is being rolled-out. ([#2602](https://github.com/expo/eas-cli/pull/2602) by [@wschurman](https://github.com/wschurman))
### 🧹 Chores
- Implement new `worker` deploy API flow. ([#2601](https://github.com/expo/eas-cli/pull/2601) by [@kitten](https://github.com/kitten)))
## [12.5.1](https://github.com/expo/eas-cli/releases/tag/v12.5.1) - 2024-09-27
### 🐛 Bug fixes
- Support assigning dev domain names in non interactive mode. ([#2595](https://github.com/expo/eas-cli/pull/2595) by [@byCedric](https://github.com/byCedric))
### 🧹 Chores
- Simplify the output of `eas deploy --json`. ([#2596](https://github.com/expo/eas-cli/pull/2596) by [@byCedric](https://github.com/byCedric))
- Support deploying Expo Router server exports without client directory. ([#2597](https://github.com/expo/eas-cli/pull/2597) by [@byCedric](https://github.com/byCedric))
- Add exit option to `eas credentials` interactive menu. ([#2570](https://github.com/expo/eas-cli/pull/2570) by [@szdziedzic](https://github.com/szdziedzic))
## [12.5.0](https://github.com/expo/eas-cli/releases/tag/v12.5.0) - 2024-09-23
### 🎉 New features
- Log command execution to assist in debugging local builds. ([#2526](https://github.com/expo/eas-cli/pull/2526) by [@trajano](https://github.com/trajano))
- Allow submitting builds in progress ([#2543](https://github.com/expo/eas-cli/pull/2543) by [@radoslawkrzemien](https://github.com/radoslawkrzemien))
- Use `EAS_DANGEROUS_OVERRIDE_ANDROID_APPLICATION_ID` and `EAS_DANGEROUS_OVERRIDE_IOS_BUNDLE_IDENTIFIER` environment variables as overrides of the Android application ID and iOS bundle identifier in managed workflow too. ([#2576](https://github.com/expo/eas-cli/pull/2576) by [@sjchmiela](https://github.com/sjchmiela))
- Add destination branch arguments to update:republish command. ([#2575](https://github.com/expo/eas-cli/pull/2575) by [@wschurman](https://github.com/wschurman))
### 🐛 Bug fixes
- Avoid malforming `app.json` with empty `.expo` object. ([#2573](https://github.com/expo/eas-cli/pull/2573) by [@byCedric](https://github.com/byCedric))
### 🧹 Chores
- Fix typo causing `worker:deploy` asset upload errors not to be shown properly. ([#2579](https://github.com/expo/eas-cli/pull/2579) by [@kitten](https://github.com/kitten))
## [12.4.1](https://github.com/expo/eas-cli/releases/tag/v12.4.1) - 2024-09-14
-16
View File
@@ -1,16 +0,0 @@
* @szdziedzic @khamilowicz @sjchmiela
packages/eas-cli/src/build @szdziedzic @khamilowicz @sjchmiela
packages/eas-cli/src/commands/build @szdziedzic @khamilowicz @sjchmiela
packages/eas-cli/src/submit @szdziedzic @khamilowicz @sjchmiela
packages/eas-cli/src/commands/submit.ts @szdziedzic @khamilowicz @sjchmiela
packages/eas-cli/src/update @EvanBacon @byCedric @wschurman
packages/eas-cli/src/commands/update @EvanBacon @byCedric @wschurman
packages/eas-cli/schema @bycedric
packages/eas-cli/src/metadata @bycedric
packages/eas-cli/src/commands/metadata @bycedric
packages/eas-json @szdziedzic @khamilowicz @sjchmiela
+1 -1
View File
@@ -1,5 +1,5 @@
{
"npmClient": "yarn",
"version": "12.5.0",
"version": "12.5.1",
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
}
+66 -62
View File
@@ -143,7 +143,7 @@ ALIASES
$ eas login
```
_See code: [packages/eas-cli/src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/account/login.ts)_
## `eas account:logout`
@@ -160,7 +160,7 @@ ALIASES
$ eas logout
```
_See code: [packages/eas-cli/src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/account/logout.ts)_
## `eas account:view`
@@ -177,7 +177,7 @@ ALIASES
$ eas whoami
```
_See code: [packages/eas-cli/src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/account/view.ts)_
## `eas analytics [STATUS]`
@@ -191,7 +191,7 @@ DESCRIPTION
display or change analytics settings
```
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v12.5.0/packages/eas-cli/src/commands/analytics.ts)_
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v12.5.1/packages/eas-cli/src/commands/analytics.ts)_
## `eas autocomplete [SHELL]`
@@ -243,7 +243,7 @@ DESCRIPTION
create a branch
```
_See code: [packages/eas-cli/src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/branch/create.ts)_
## `eas branch:delete [NAME]`
@@ -264,7 +264,7 @@ DESCRIPTION
delete a branch
```
_See code: [packages/eas-cli/src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/branch/delete.ts)_
## `eas branch:list`
@@ -284,7 +284,7 @@ DESCRIPTION
list all branches
```
_See code: [packages/eas-cli/src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/branch/list.ts)_
## `eas branch:rename`
@@ -304,7 +304,7 @@ DESCRIPTION
rename a branch
```
_See code: [packages/eas-cli/src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/branch/rename.ts)_
## `eas branch:view [NAME]`
@@ -327,7 +327,7 @@ DESCRIPTION
view a branch
```
_See code: [packages/eas-cli/src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/branch/view.ts)_
## `eas build`
@@ -364,7 +364,7 @@ DESCRIPTION
start a build
```
_See code: [packages/eas-cli/src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/build/index.ts)_
## `eas build:cancel [BUILD_ID]`
@@ -383,7 +383,7 @@ DESCRIPTION
cancel a build
```
_See code: [packages/eas-cli/src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/build/cancel.ts)_
## `eas build:configure`
@@ -400,7 +400,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/build/configure.ts)_
## `eas build:delete [BUILD_ID]`
@@ -419,7 +419,7 @@ DESCRIPTION
delete a build
```
_See code: [packages/eas-cli/src/commands/build/delete.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/build/delete.ts)_
## `eas build:inspect`
@@ -454,7 +454,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/build/inspect.ts)_
## `eas build:list`
@@ -504,7 +504,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/build/list.ts)_
## `eas build:resign`
@@ -533,7 +533,7 @@ DESCRIPTION
re-sign a build archive
```
_See code: [packages/eas-cli/src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/build/resign.ts)_
## `eas build:run`
@@ -559,7 +559,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/build/run.ts)_
## `eas build:submit`
@@ -609,7 +609,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/build/version/get.ts)_
## `eas build:version:set`
@@ -628,7 +628,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/build/version/set.ts)_
## `eas build:version:sync`
@@ -647,7 +647,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/build/version/sync.ts)_
## `eas build:view [BUILD_ID]`
@@ -664,7 +664,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/build/view.ts)_
## `eas channel:create [NAME]`
@@ -685,7 +685,7 @@ DESCRIPTION
create a channel
```
_See code: [packages/eas-cli/src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/channel/create.ts)_
## `eas channel:edit [NAME]`
@@ -707,7 +707,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/channel/edit.ts)_
## `eas channel:list`
@@ -727,7 +727,7 @@ DESCRIPTION
list all channels
```
_See code: [packages/eas-cli/src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/channel/list.ts)_
## `eas channel:rollout [CHANNEL]`
@@ -760,7 +760,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/channel/rollout.ts)_
## `eas channel:view [NAME]`
@@ -783,7 +783,7 @@ DESCRIPTION
view a channel
```
_See code: [packages/eas-cli/src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/channel/view.ts)_
## `eas config`
@@ -804,7 +804,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/v12.5.0/packages/eas-cli/src/commands/config.ts)_
_See code: [packages/eas-cli/src/commands/config.ts](https://github.com/expo/eas-cli/blob/v12.5.1/packages/eas-cli/src/commands/config.ts)_
## `eas credentials`
@@ -821,7 +821,7 @@ DESCRIPTION
manage credentials
```
_See code: [packages/eas-cli/src/commands/credentials/index.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/credentials/index.ts)_
## `eas credentials:configure-build`
@@ -839,7 +839,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/credentials/configure-build.ts)_
## `eas device:create`
@@ -853,7 +853,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/device/create.ts)_
## `eas device:delete`
@@ -873,7 +873,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/device/delete.ts)_
## `eas device:list`
@@ -894,7 +894,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/device/list.ts)_
## `eas device:rename`
@@ -915,7 +915,7 @@ DESCRIPTION
rename a registered device
```
_See code: [packages/eas-cli/src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/device/rename.ts)_
## `eas device:view [UDID]`
@@ -929,7 +929,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/device/view.ts)_
## `eas diagnostics`
@@ -943,7 +943,7 @@ DESCRIPTION
display environment info
```
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v12.5.0/packages/eas-cli/src/commands/diagnostics.ts)_
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v12.5.1/packages/eas-cli/src/commands/diagnostics.ts)_
## `eas help [COMMAND]`
@@ -1051,7 +1051,7 @@ DESCRIPTION
validate the local store configuration
```
_See code: [packages/eas-cli/src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/metadata/lint.ts)_
## `eas metadata:pull`
@@ -1068,7 +1068,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/metadata/pull.ts)_
## `eas metadata:push`
@@ -1085,7 +1085,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/metadata/push.ts)_
## `eas onboarding [TARGET_PROJECT_DIRECTORY]`
@@ -1115,7 +1115,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/v12.5.0/packages/eas-cli/src/commands/open.ts)_
_See code: [packages/eas-cli/src/commands/open.ts](https://github.com/expo/eas-cli/blob/v12.5.1/packages/eas-cli/src/commands/open.ts)_
## `eas project:info`
@@ -1129,7 +1129,7 @@ DESCRIPTION
information about the current project
```
_See code: [packages/eas-cli/src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/project/info.ts)_
## `eas project:init`
@@ -1152,7 +1152,7 @@ ALIASES
$ eas init
```
_See code: [packages/eas-cli/src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/project/init.ts)_
## `eas project:onboarding [TARGET_PROJECT_DIRECTORY]`
@@ -1170,7 +1170,7 @@ ALIASES
$ eas onboarding
```
_See code: [packages/eas-cli/src/commands/project/onboarding.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/project/onboarding.ts)_
## `eas secret:create`
@@ -1193,7 +1193,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/v12.5.0/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/v12.5.1/packages/eas-cli/src/commands/secret/create.ts)_
## `eas secret:delete`
@@ -1211,7 +1211,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/v12.5.0/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/v12.5.1/packages/eas-cli/src/commands/secret/delete.ts)_
## `eas secret:list`
@@ -1225,7 +1225,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/v12.5.0/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/v12.5.1/packages/eas-cli/src/commands/secret/list.ts)_
## `eas secret:push`
@@ -1245,7 +1245,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/v12.5.0/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/v12.5.1/packages/eas-cli/src/commands/secret/push.ts)_
## `eas submit`
@@ -1276,7 +1276,7 @@ ALIASES
$ eas build:submit
```
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v12.5.0/packages/eas-cli/src/commands/submit.ts)_
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v12.5.1/packages/eas-cli/src/commands/submit.ts)_
## `eas update`
@@ -1310,7 +1310,7 @@ DESCRIPTION
publish an update group
```
_See code: [packages/eas-cli/src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/update/index.ts)_
## `eas update:configure`
@@ -1328,7 +1328,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/update/configure.ts)_
## `eas update:delete GROUPID`
@@ -1349,7 +1349,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/update/delete.ts)_
## `eas update:list`
@@ -1371,7 +1371,7 @@ DESCRIPTION
view the recent updates
```
_See code: [packages/eas-cli/src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/update/list.ts)_
## `eas update:republish`
@@ -1379,14 +1379,18 @@ roll back to an existing update
```
USAGE
$ eas update:republish [--channel <value> | --branch <value> | --group <value>] [-m <value>] [-p android|ios|all]
[--private-key-path <value>] [--json --non-interactive]
$ eas update:republish [--channel <value> | --branch <value> | --group <value>] [--destination-channel <value> |
--destination-branch <value>] [-m <value>] [-p android|ios|all] [--private-key-path <value>] [--json
--non-interactive]
FLAGS
-m, --message=<value> Short message describing the republished update group
-p, --platform=(android|ios|all) [default: all]
--branch=<value> Branch name to select an update group to republish from
--channel=<value> Channel name to select an update group to republish from
--destination-branch=<value> Branch name to republish to if republishing to a different branch
--destination-channel=<value> Channel name to select a branch to republish to if republishing to a different
branch
--group=<value> Update group ID to republish
--json Enable JSON output, non-JSON messages will be printed to stderr.
--non-interactive Run the command in non-interactive mode.
@@ -1399,7 +1403,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/update/republish.ts)_
## `eas update:roll-back-to-embedded`
@@ -1427,7 +1431,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/update/roll-back-to-embedded.ts)_
## `eas update:rollback`
@@ -1447,7 +1451,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/v12.5.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/v12.5.1/packages/eas-cli/src/commands/update/rollback.ts)_
## `eas update:view GROUPID`
@@ -1467,7 +1471,7 @@ DESCRIPTION
update group details
```
_See code: [packages/eas-cli/src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/update/view.ts)_
## `eas webhook:create`
@@ -1488,7 +1492,7 @@ DESCRIPTION
create a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/webhook/create.ts)_
## `eas webhook:delete [ID]`
@@ -1508,7 +1512,7 @@ DESCRIPTION
delete a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/webhook/delete.ts)_
## `eas webhook:list`
@@ -1526,7 +1530,7 @@ DESCRIPTION
list webhooks
```
_See code: [packages/eas-cli/src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/webhook/list.ts)_
## `eas webhook:update`
@@ -1548,7 +1552,7 @@ DESCRIPTION
update a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/webhook/update.ts)_
## `eas webhook:view ID`
@@ -1565,7 +1569,7 @@ DESCRIPTION
view a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v12.5.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/v12.5.1/packages/eas-cli/src/commands/webhook/view.ts)_
## `eas whoami`
+76
View File
@@ -24366,6 +24366,49 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "DeleteWorkerDeploymentResult",
"description": null,
"fields": [
{
"name": "deploymentIdentifier",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "WorkerDeploymentIdentifier",
"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
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "DeployServerlessFunctionResult",
@@ -25434,6 +25477,39 @@
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "deleteWorkerDeployment",
"description": null,
"args": [
{
"name": "workerDeploymentId",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "DeleteWorkerDeploymentResult",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "eas-cli",
"description": "EAS command line tool",
"version": "12.5.0",
"version": "12.5.1",
"author": "Expo <[email protected]>",
"bin": {
"eas": "./bin/run"
@@ -13,14 +13,12 @@ function isEnvironment(env: string): env is EnvironmentVariableEnvironment {
}
export async function evaluateConfigWithEnvVarsAsync<Config extends { projectId: string }, Opts>({
flags,
buildProfile,
buildProfileName,
graphqlClient,
getProjectConfig,
opts,
}: {
flags: { environment?: string };
buildProfile: BuildProfile;
buildProfileName: string;
graphqlClient: ExpoGraphqlClient | null;
@@ -34,7 +32,6 @@ export async function evaluateConfigWithEnvVarsAsync<Config extends { projectId:
}
const { projectId } = await getProjectConfig({ env: buildProfile.env, ...opts });
const env = await resolveEnvVarsAsync({
flags,
buildProfile,
buildProfileName,
graphqlClient,
@@ -46,22 +43,18 @@ export async function evaluateConfigWithEnvVarsAsync<Config extends { projectId:
}
async function resolveEnvVarsAsync({
flags,
buildProfile,
buildProfileName,
graphqlClient,
projectId,
}: {
flags: { environment?: string };
buildProfile: BuildProfile;
buildProfileName: string;
graphqlClient: ExpoGraphqlClient;
projectId: string;
}): Promise<Env> {
const environment =
flags.environment ??
buildProfile.environment?.toUpperCase() ??
process.env.EAS_CURRENT_ENVIRONMENT;
buildProfile.environment?.toUpperCase() ?? process.env.EAS_CURRENT_ENVIRONMENT;
if (!environment || !isEnvironment(environment)) {
Log.log(
@@ -33,7 +33,6 @@ import {
BuildFragment,
BuildStatus,
BuildWithSubmissionsFragment,
EnvironmentVariableEnvironment,
SubmissionFragment,
} from '../graphql/generated';
import { BuildQuery } from '../graphql/queries/BuildQuery';
@@ -98,7 +97,6 @@ export interface BuildFlags {
buildLoggerLevel?: LoggerLevel;
freezeCredentials: boolean;
repack: boolean;
environment?: EnvironmentVariableEnvironment;
}
export async function runBuildAndSubmitAsync(
@@ -195,7 +193,6 @@ export async function runBuildAndSubmitAsync(
const platform = toAppPlatform(buildProfile.platform);
const { env } = await evaluateConfigWithEnvVarsAsync({
flags,
buildProfile: buildProfile.profile,
buildProfileName: buildProfile.profileName,
graphqlClient,
@@ -38,21 +38,6 @@ export const EASEnvironmentFlag = {
}),
};
// NOTE: Used in build commands, should be replaced with EASEnvironmentFlag when
// the feature is public
export const EASEnvironmentFlagHidden = {
environment: Flags.enum<EnvironmentVariableEnvironment>({
description: "Environment variable's environment",
parse: upperCaseAsync,
hidden: true,
options: mapToLowercase([
EnvironmentVariableEnvironment.Development,
EnvironmentVariableEnvironment.Preview,
EnvironmentVariableEnvironment.Production,
]),
}),
};
export const EASVariableFormatFlag = {
format: Flags.enum({
description: 'Output format',
+2 -5
View File
@@ -10,8 +10,8 @@ import path from 'path';
import { LocalBuildMode } from '../../build/local';
import { BuildFlags, runBuildAndSubmitAsync } from '../../build/runBuildAndSubmit';
import EasCommand from '../../commandUtils/EasCommand';
import { EASEnvironmentFlagHidden, EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
import { EnvironmentVariableEnvironment, StatuspageServiceName } from '../../graphql/generated';
import { EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
import { StatuspageServiceName } from '../../graphql/generated';
import Log, { link } from '../../log';
import { RequestedPlatform, selectRequestedPlatformAsync } from '../../platform';
import { selectAsync } from '../../prompts';
@@ -37,7 +37,6 @@ interface RawBuildFlags {
'build-logger-level'?: LoggerLevel;
'freeze-credentials': boolean;
repack: boolean;
environment?: EnvironmentVariableEnvironment;
}
export default class Build extends EasCommand {
@@ -117,7 +116,6 @@ export default class Build extends EasCommand {
description: 'Use the golden dev client build repack flow as it works for onboarding',
}),
...EasNonInteractiveAndJsonFlags,
...EASEnvironmentFlagHidden,
};
static override contextDefinition = {
@@ -232,7 +230,6 @@ export default class Build extends EasCommand {
buildLoggerLevel: flags['build-logger-level'],
freezeCredentials: flags['freeze-credentials'],
repack: flags.repack,
environment: flags.environment,
};
}
@@ -13,7 +13,7 @@ import { listAndSelectBuildOnAppAsync } from '../../build/queries';
import { printBuildResults, printLogsUrls } from '../../build/utils/printBuildInfo';
import EasCommand from '../../commandUtils/EasCommand';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { EASEnvironmentFlagHidden, EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
import { EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
import { EasPaginatedQueryFlags } from '../../commandUtils/pagination';
import { CredentialsContext } from '../../credentials/context';
import {
@@ -93,7 +93,6 @@ export default class BuildResign extends EasCommand {
}),
...EasPaginatedQueryFlags,
...EasNonInteractiveAndJsonFlags,
...EASEnvironmentFlagHidden,
};
static override contextDefinition = {
@@ -147,7 +146,6 @@ export default class BuildResign extends EasCommand {
);
const { exp, projectId, env } = await evaluateConfigWithEnvVarsAsync({
flags,
buildProfile,
buildProfileName: flags.targetProfile ?? 'production',
graphqlClient,
@@ -5,10 +5,7 @@ import chalk from 'chalk';
import { evaluateConfigWithEnvVarsAsync } from '../../../build/evaluateConfigWithEnvVarsAsync';
import EasCommand from '../../../commandUtils/EasCommand';
import {
EASEnvironmentFlagHidden,
EasNonInteractiveAndJsonFlags,
} from '../../../commandUtils/flags';
import { EasNonInteractiveAndJsonFlags } from '../../../commandUtils/flags';
import { AppVersionQuery } from '../../../graphql/queries/AppVersionQuery';
import { toAppPlatform } from '../../../graphql/types/AppPlatform';
import Log from '../../../log';
@@ -35,7 +32,6 @@ export default class BuildVersionGetView extends EasCommand {
'Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.',
helpValue: 'PROFILE_NAME',
}),
...EASEnvironmentFlagHidden,
...EasNonInteractiveAndJsonFlags,
};
@@ -80,7 +76,6 @@ export default class BuildVersionGetView extends EasCommand {
const results: { [key in Platform]?: string } = {};
for (const { profile, platform } of buildProfiles) {
const { exp, projectId, env } = await evaluateConfigWithEnvVarsAsync({
flags,
buildProfile: profile,
buildProfileName: flags.profile ?? 'production',
graphqlClient,
@@ -6,7 +6,6 @@ import chalk from 'chalk';
import { evaluateConfigWithEnvVarsAsync } from '../../../build/evaluateConfigWithEnvVarsAsync';
import EasCommand from '../../../commandUtils/EasCommand';
import { EASEnvironmentFlagHidden } from '../../../commandUtils/flags';
import { AppVersionMutation } from '../../../graphql/mutations/AppVersionMutation';
import { AppVersionQuery } from '../../../graphql/queries/AppVersionQuery';
import { toAppPlatform } from '../../../graphql/types/AppPlatform';
@@ -37,7 +36,6 @@ export default class BuildVersionSetView extends EasCommand {
'Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.',
helpValue: 'PROFILE_NAME',
}),
...EASEnvironmentFlagHidden,
};
static override contextDefinition = {
@@ -68,7 +66,6 @@ export default class BuildVersionSetView extends EasCommand {
);
const { exp, projectId, env } = await evaluateConfigWithEnvVarsAsync({
flags,
buildProfile: profile,
buildProfileName: flags.profile ?? 'production',
graphqlClient,
@@ -8,7 +8,6 @@ import { updateNativeVersionsAsync as updateAndroidNativeVersionsAsync } from '.
import { evaluateConfigWithEnvVarsAsync } from '../../../build/evaluateConfigWithEnvVarsAsync';
import { updateNativeVersionsAsync as updateIosNativeVersionsAsync } from '../../../build/ios/version';
import EasCommand from '../../../commandUtils/EasCommand';
import { EASEnvironmentFlagHidden } from '../../../commandUtils/flags';
import { AppVersionQuery } from '../../../graphql/queries/AppVersionQuery';
import { toAppPlatform } from '../../../graphql/types/AppPlatform';
import Log from '../../../log';
@@ -56,7 +55,6 @@ export default class BuildVersionSyncView extends EasCommand {
'Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.',
helpValue: 'PROFILE_NAME',
}),
...EASEnvironmentFlagHidden,
};
static override contextDefinition = {
@@ -91,7 +89,6 @@ export default class BuildVersionSyncView extends EasCommand {
});
for (const profileInfo of buildProfiles) {
const { exp, projectId, env } = await evaluateConfigWithEnvVarsAsync({
flags,
buildProfile: profileInfo.profile,
buildProfileName: profileInfo.profileName,
graphqlClient,
+1 -3
View File
@@ -7,7 +7,7 @@ import chalk from 'chalk';
import { evaluateConfigWithEnvVarsAsync } from '../build/evaluateConfigWithEnvVarsAsync';
import EasCommand from '../commandUtils/EasCommand';
import { createGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
import { EASEnvironmentFlagHidden, EasNonInteractiveAndJsonFlags } from '../commandUtils/flags';
import { EasNonInteractiveAndJsonFlags } from '../commandUtils/flags';
import { toAppPlatform } from '../graphql/types/AppPlatform';
import Log from '../log';
import { appPlatformEmojis } from '../platform';
@@ -29,7 +29,6 @@ export default class Config extends EasCommand {
'eas-json-only': Flags.boolean({
hidden: true,
}),
...EASEnvironmentFlagHidden,
...EasNonInteractiveAndJsonFlags,
};
@@ -94,7 +93,6 @@ export default class Config extends EasCommand {
});
const graphqlClient = createGraphqlClient(authenticationInfo);
const { exp: appConfig } = await evaluateConfigWithEnvVarsAsync({
flags,
buildProfile: profile,
buildProfileName: profileName,
graphqlClient,
+185
View File
@@ -0,0 +1,185 @@
import spawnAsync from '@expo/spawn-async';
import chalk from 'chalk';
import EasCommand from '../../commandUtils/EasCommand';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { EASEnvironmentFlag, EASNonInteractiveFlag } from '../../commandUtils/flags';
import { EnvironmentVariableEnvironment } from '../../graphql/generated';
import { EnvironmentVariablesQuery } from '../../graphql/queries/EnvironmentVariablesQuery';
import Log from '../../log';
import { promptVariableEnvironmentAsync } from '../../utils/prompts';
type ParsedFlags =
| {
nonInteractive: true;
environment: EnvironmentVariableEnvironment;
}
| {
nonInteractive: false;
environment?: EnvironmentVariableEnvironment;
};
interface RawFlags {
environment?: EnvironmentVariableEnvironment;
'non-interactive': boolean;
}
export default class EnvExec extends EasCommand {
static override description =
'execute a bash command with environment variables from the selected environment';
static override hidden = true;
static override contextDefinition = {
...this.ContextOptions.ProjectConfig,
...this.ContextOptions.LoggedIn,
};
static override flags = {
...EASEnvironmentFlag,
...EASNonInteractiveFlag,
};
static override args = [
{
name: 'BASH_COMMAND',
required: true,
description: 'bash command to execute with the environment variables from the environment',
},
];
async runAsync(): Promise<void> {
const {
flags,
args: { BASH_COMMAND: command },
} = await this.parse(EnvExec);
const parsedFlags = this.sanitizeFlags(flags);
const {
privateProjectConfig: { projectId },
loggedIn: { graphqlClient },
} = await this.getContextAsync(EnvExec, {
nonInteractive: parsedFlags.nonInteractive,
});
const environment =
parsedFlags.environment ?? (await promptVariableEnvironmentAsync(parsedFlags.nonInteractive));
const environmentVariables = await this.loadEnvironmentVariablesAsync({
graphqlClient,
projectId,
environment,
});
await this.runCommandWithEnvVarsAsync({ command, environmentVariables });
}
private sanitizeFlags(rawFlags: RawFlags): ParsedFlags {
const environment = rawFlags.environment;
if (rawFlags['non-interactive']) {
if (!environment) {
throw new Error(
'You must specify an environment when running in non-interactive mode. Use the --environment flag.'
);
}
return {
nonInteractive: true,
environment,
};
}
return {
nonInteractive: false,
environment: rawFlags.environment,
};
}
private async runCommandWithEnvVarsAsync({
command,
environmentVariables,
}: {
command: string;
environmentVariables: Record<string, string>;
}): Promise<void> {
Log.log(`Running command: ${chalk.bold(command)}`);
const spawnPromise = spawnAsync('bash', ['-c', command], {
stdio: ['inherit', 'pipe', 'pipe'],
env: {
...process.env,
...environmentVariables,
},
});
const {
child: { stdout, stderr },
} = spawnPromise;
if (!stdout || !stderr) {
throw new Error(`Failed to spawn ${command}`);
}
stdout.on('data', data => {
for (const line of data.toString().trim().split('\n')) {
Log.log(`${chalk.gray('[stdout]')} ${line}`);
}
});
stderr.on('data', data => {
for (const line of data.toString().trim().split('\n')) {
Log.warn(`${chalk.gray('[stderr]')} ${line}`);
}
});
try {
await spawnPromise;
} catch (error) {
Log.error(`❌ ${chalk.bold(command)} failed`);
throw error;
}
}
private async loadEnvironmentVariablesAsync({
graphqlClient,
projectId,
environment,
}: {
graphqlClient: ExpoGraphqlClient;
projectId: string;
environment: EnvironmentVariableEnvironment;
}): Promise<Record<string, string>> {
const environmentVariablesQueryResult =
await EnvironmentVariablesQuery.byAppIdWithSensitiveAsync(graphqlClient, {
appId: projectId,
environment,
});
const secretEnvironmentVariables = environmentVariablesQueryResult.filter(
({ value }) => !value
);
if (secretEnvironmentVariables.length > 0) {
Log.warn(`The following environment variables are secret and cannot be downloaded locally:`);
for (const { name } of secretEnvironmentVariables) {
Log.warn(`- ${name}`);
}
Log.warn('Proceeding with the rest of the environment variables.');
Log.newLine();
}
const nonSecretEnvironmentVariables = environmentVariablesQueryResult.filter(
({ value }) => !!value
);
if (nonSecretEnvironmentVariables.length === 0) {
throw new Error('No readable environment variables found for the selected environment.');
}
Log.log(
`Loaded environment variables for the selected environment "${environment.toLowerCase()}":`
);
for (const { name } of nonSecretEnvironmentVariables) {
Log.log(`- ${name}`);
}
Log.newLine();
const environmentVariables: Record<string, string> = {};
for (const { name, value } of nonSecretEnvironmentVariables) {
if (value) {
environmentVariables[name] = value;
}
}
return environmentVariables;
}
}
@@ -21,7 +21,7 @@ import { UpdateFragment } from '../../../graphql/generated';
import { PublishMutation } from '../../../graphql/mutations/PublishMutation';
import { AppQuery } from '../../../graphql/queries/AppQuery';
import { collectAssetsAsync, uploadAssetsAsync } from '../../../project/publish';
import { getBranchNameFromChannelNameAsync } from '../../../update/getBranchNameFromChannelNameAsync';
import { getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync } from '../../../update/getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync';
import { resolveVcsClient } from '../../../vcs';
const projectRoot = '/test-project';
@@ -47,7 +47,7 @@ jest.mock('@expo/config-plugins');
jest.mock('../../../branch/queries');
jest.mock('../../../commandUtils/context/contextUtils/getProjectIdAsync');
jest.mock('../../../update/configure');
jest.mock('../../../update/getBranchNameFromChannelNameAsync');
jest.mock('../../../update/getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync');
jest.mock('../../../graphql/mutations/PublishMutation');
jest.mock('../../../graphql/queries/AppQuery');
jest.mock('../../../graphql/queries/UpdateQuery');
@@ -106,7 +106,9 @@ describe(UpdatePublish.name, () => {
const { projectId } = mockTestProject();
const { platforms, runtimeVersion } = mockTestExport();
jest.mocked(getBranchNameFromChannelNameAsync).mockResolvedValue('branchFromChannel');
jest
.mocked(getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync)
.mockResolvedValue({ branchId: 'branch123', branchName: 'branchFromChannel' });
jest.mocked(ensureBranchExistsAsync).mockResolvedValue({
branchId: 'branch123',
createdBranch: false,
@@ -11,8 +11,9 @@ import { jester } from '../../../credentials/__tests__/fixtures-constants';
import { UpdateFragment } from '../../../graphql/generated';
import { PublishMutation } from '../../../graphql/mutations/PublishMutation';
import { AppQuery } from '../../../graphql/queries/AppQuery';
import { BranchQuery } from '../../../graphql/queries/BranchQuery';
import { UpdateQuery } from '../../../graphql/queries/UpdateQuery';
import { getBranchNameFromChannelNameAsync } from '../../../update/getBranchNameFromChannelNameAsync';
import { getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync } from '../../../update/getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync';
import { selectUpdateGroupOnBranchAsync } from '../../../update/queries';
import {
getCodeSigningInfoAsync,
@@ -44,7 +45,8 @@ jest.mock('../../../commandUtils/context/contextUtils/getProjectIdAsync');
jest.mock('../../../graphql/mutations/PublishMutation');
jest.mock('../../../graphql/queries/AppQuery');
jest.mock('../../../graphql/queries/UpdateQuery');
jest.mock('../../../update/getBranchNameFromChannelNameAsync');
jest.mock('../../../graphql/queries/BranchQuery');
jest.mock('../../../update/getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync');
jest.mock('../../../update/queries');
jest.mock('../../../ora', () => ({
ora: () => ({
@@ -57,6 +59,7 @@ jest.mock('../../../fetch');
describe(UpdateRepublish.name, () => {
afterEach(() => {
vol.reset();
jest.resetAllMocks();
});
it('errors when providing both --group and --branch', async () => {
@@ -89,6 +92,16 @@ describe(UpdateRepublish.name, () => {
);
});
it('errors when providing both --destination-channel and --destination-branch', async () => {
const flags = ['--group=1234', '--destination-channel=test', '--destination-branch=wat'];
mockTestProject();
await expect(new UpdateRepublish(flags, commandOptions).run()).rejects.toThrow(
/--destination-branch=wat cannot also be provided when using --destination-channel/
);
});
it('errors when update group is empty', async () => {
const flags = ['--group=1234'];
@@ -271,7 +284,9 @@ describe(UpdateRepublish.name, () => {
mockTestProject();
// Mock resolving the channel to branch name, only valid for a single branch connected
jest.mocked(getBranchNameFromChannelNameAsync).mockResolvedValue('branchFromChannel');
jest
.mocked(getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync)
.mockResolvedValue({ branchId: updateStub.branch.id, branchName: 'branchFromChannel' });
// Mock the prompt to ask the user which update to republish, from branch
jest.mocked(selectUpdateGroupOnBranchAsync).mockResolvedValue([updateStub]);
// Mock mutations to store the new update
@@ -306,6 +321,94 @@ describe(UpdateRepublish.name, () => {
])
);
});
it('republishes to a different branch when --destination-branch is supplied', async () => {
const flags = ['--branch=branch123', '--message=test-republish', '--destination-branch=other'];
mockTestProject();
// Mock the prompt to ask the user which update to republish, from branch
jest.mocked(selectUpdateGroupOnBranchAsync).mockResolvedValue([updateStub]);
// Mock mutations to store the new update
jest.mocked(PublishMutation.publishUpdateGroupAsync).mockResolvedValue([
{
...updateStub,
branch: { id: 'other-id', name: 'other' },
id: 'update-new',
platform: 'ios',
manifestPermalink: 'https://expo.dev/@test/test-project/manifest',
},
]);
jest.mocked(BranchQuery.getBranchByNameAsync).mockResolvedValue({
id: 'other-id',
name: 'other',
});
await new UpdateRepublish(flags, commandOptions).run();
expect(selectUpdateGroupOnBranchAsync).toHaveBeenCalledWith(
expect.any(Object), // graphql client
expect.objectContaining({ branchName: 'branch123' })
);
expect(PublishMutation.publishUpdateGroupAsync).toHaveBeenCalledWith(
expect.any(Object), // graphql client
expect.arrayContaining([
expect.objectContaining({
branchId: 'other-id',
runtimeVersion: updateStub.runtimeVersion,
updateInfoGroup: expect.objectContaining({
ios: expect.any(Object),
}),
gitCommitHash: updateStub.gitCommitHash,
awaitingCodeSigningInfo: false,
}),
])
);
});
it('republishes to a different branch when --destination-channel is supplied', async () => {
const flags = ['--branch=branch123', '--message=test-republish', '--destination-channel=blah'];
mockTestProject();
// Mock the prompt to ask the user which update to republish, from branch
jest.mocked(selectUpdateGroupOnBranchAsync).mockResolvedValue([updateStub]);
// Mock mutations to store the new update
jest.mocked(PublishMutation.publishUpdateGroupAsync).mockResolvedValue([
{
...updateStub,
branch: { id: 'other-id', name: 'other' },
id: 'update-new',
platform: 'ios',
manifestPermalink: 'https://expo.dev/@test/test-project/manifest',
},
]);
jest
.mocked(getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync)
.mockResolvedValue({ branchId: 'blah-id', branchName: 'blah' });
await new UpdateRepublish(flags, commandOptions).run();
expect(selectUpdateGroupOnBranchAsync).toHaveBeenCalledWith(
expect.any(Object), // graphql client
expect.objectContaining({ branchName: 'branch123' })
);
expect(PublishMutation.publishUpdateGroupAsync).toHaveBeenCalledWith(
expect.any(Object), // graphql client
expect.arrayContaining([
expect.objectContaining({
branchId: 'blah-id',
runtimeVersion: updateStub.runtimeVersion,
updateInfoGroup: expect.objectContaining({
ios: expect.any(Object),
}),
gitCommitHash: updateStub.gitCommitHash,
awaitingCodeSigningInfo: false,
}),
])
);
});
});
/** Create a new in-memory project, based on src/commands/project/__tests__/init.test.ts */
@@ -19,7 +19,7 @@ import { jester } from '../../../credentials/__tests__/fixtures-constants';
import { UpdateFragment } from '../../../graphql/generated';
import { PublishMutation } from '../../../graphql/mutations/PublishMutation';
import { AppQuery } from '../../../graphql/queries/AppQuery';
import { getBranchNameFromChannelNameAsync } from '../../../update/getBranchNameFromChannelNameAsync';
import { getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync } from '../../../update/getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync';
import { resolveVcsClient } from '../../../vcs';
import UpdateRollBackToEmbedded from '../roll-back-to-embedded';
@@ -50,7 +50,7 @@ jest.mock('../../../project/projectUtils', () => ({
enforceRollBackToEmbeddedUpdateSupportAsync: jest.fn(),
}));
jest.mock('../../../update/configure');
jest.mock('../../../update/getBranchNameFromChannelNameAsync');
jest.mock('../../../update/getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync');
jest.mock('../../../graphql/mutations/PublishMutation');
jest.mock('../../../graphql/queries/AppQuery');
jest.mock('../../../graphql/queries/UpdateQuery');
@@ -112,7 +112,9 @@ describe(UpdateRollBackToEmbedded.name, () => {
const runtimeVersion = 'exposdk:47.0.0';
jest.mocked(Updates.getRuntimeVersionAsync).mockResolvedValue(runtimeVersion);
jest.mocked(getBranchNameFromChannelNameAsync).mockResolvedValue('branchFromChannel');
jest
.mocked(getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync)
.mockResolvedValue({ branchId: updateStub.branch.id, branchName: 'branchFromChannel' });
jest.mocked(ensureBranchExistsAsync).mockResolvedValue({
branchId: 'branch123',
createdBranch: false,
+1 -1
View File
@@ -103,7 +103,7 @@ export default class UpdateEdit extends EasCommand {
});
if (!percentage) {
Log.log('Aborted.');
Log.log('Aborted .');
return;
}
@@ -7,10 +7,11 @@ import EasCommand from '../../commandUtils/EasCommand';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
import { getPaginatedQueryOptions } from '../../commandUtils/pagination';
import { BranchQuery } from '../../graphql/queries/BranchQuery';
import { UpdateQuery } from '../../graphql/queries/UpdateQuery';
import Log from '../../log';
import { promptAsync } from '../../prompts';
import { getBranchNameFromChannelNameAsync } from '../../update/getBranchNameFromChannelNameAsync';
import { getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync } from '../../update/getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync';
import { selectUpdateGroupOnBranchAsync } from '../../update/queries';
import { UpdateToRepublish, republishAsync } from '../../update/republish';
import { truncateString as truncateUpdateMessage } from '../../update/utils';
@@ -22,6 +23,8 @@ const defaultRepublishPlatforms: Platform[] = ['android', 'ios'];
type UpdateRepublishRawFlags = {
branch?: string;
channel?: string;
'destination-channel'?: string;
'destination-branch'?: string;
group?: string;
message?: string;
platform: string;
@@ -33,6 +36,8 @@ type UpdateRepublishRawFlags = {
type UpdateRepublishFlags = {
branchName?: string;
channelName?: string;
destinationChannelName?: string;
destinationBranchName?: string;
groupId?: string;
updateMessage?: string;
platform: Platform[];
@@ -57,6 +62,15 @@ export default class UpdateRepublish extends EasCommand {
description: 'Update group ID to republish',
exclusive: ['branch', 'channel'],
}),
'destination-channel': Flags.string({
description:
'Channel name to select a branch to republish to if republishing to a different branch',
exclusive: ['destination-branch'],
}),
'destination-branch': Flags.string({
description: 'Branch name to republish to if republishing to a different branch',
exclusive: ['destination-channel'],
}),
message: Flags.string({
char: 'm',
description: 'Short message describing the republished update group',
@@ -130,13 +144,21 @@ export default class UpdateRepublish extends EasCommand {
);
}
const updateMessage = await getOrAskUpdateMessageAsync(updatesToPublish, flags);
const arbitraryUpdate = updatesToPublish[0];
const targetBranch = await getOrAskTargetBranchAsync(
graphqlClient,
projectId,
flags,
arbitraryUpdate
);
const updateMessage = await getOrAskUpdateMessageAsync(updatesToPublish, flags);
await republishAsync({
graphqlClient,
app: { exp, projectId },
updatesToPublish,
targetBranch: { branchId: arbitraryUpdate.branchId, branchName: arbitraryUpdate.branchName },
targetBranch,
updateMessage,
codeSigningInfo,
json: flags.json,
@@ -147,6 +169,8 @@ export default class UpdateRepublish extends EasCommand {
const branchName = rawFlags.branch;
const channelName = rawFlags.channel;
const groupId = rawFlags.group;
const destinationChannelName = rawFlags['destination-channel'];
const destinationBranchName = rawFlags['destination-branch'];
const nonInteractive = rawFlags['non-interactive'];
const privateKeyPath = rawFlags['private-key-path'];
@@ -160,6 +184,8 @@ export default class UpdateRepublish extends EasCommand {
return {
branchName,
channelName,
destinationChannelName,
destinationBranchName,
groupId,
platform,
updateMessage: rawFlags.message,
@@ -170,6 +196,34 @@ export default class UpdateRepublish extends EasCommand {
}
}
async function getOrAskTargetBranchAsync(
graphqlClient: ExpoGraphqlClient,
projectId: string,
flags: UpdateRepublishFlags,
arbitraryUpdate: UpdateToRepublish
): Promise<{ branchId: string; branchName: string }> {
// if branch name supplied, use that
if (flags.destinationBranchName) {
const branch = await BranchQuery.getBranchByNameAsync(graphqlClient, {
appId: projectId,
name: flags.destinationBranchName,
});
return { branchId: branch.id, branchName: branch.name };
}
// if provided channel name but was non-interactive
if (flags.destinationChannelName) {
return await getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync(
graphqlClient,
projectId,
flags.destinationChannelName
);
}
// if neither provided, assume republish on same branch
return { branchId: arbitraryUpdate.branchId, branchName: arbitraryUpdate.branchName };
}
/** Retrieve the update group from either the update group id, or select from branch name. */
async function getOrAskUpdatesAsync(
graphqlClient: ExpoGraphqlClient,
@@ -293,7 +347,11 @@ async function askUpdatesFromChannelNameAsync(
nonInteractive,
}: { projectId: string; channelName: string; json: boolean; nonInteractive: boolean }
): Promise<UpdateToRepublish[]> {
const branchName = await getBranchNameFromChannelNameAsync(graphqlClient, projectId, channelName);
const { branchName } = await getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync(
graphqlClient,
projectId,
channelName
);
return await askUpdatesFromBranchNameAsync(graphqlClient, {
projectId,
+63 -29
View File
@@ -6,10 +6,7 @@ import * as path from 'node:path';
import EasCommand from '../../commandUtils/EasCommand';
import { EASEnvironmentFlag, EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
import {
EnvironmentVariableEnvironment,
WorkerDeploymentAliasFragment,
} from '../../graphql/generated';
import { EnvironmentVariableEnvironment } from '../../graphql/generated';
import Log from '../../log';
import { ora } from '../../ora';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
@@ -20,7 +17,12 @@ import {
assignWorkerDeploymentProductionAsync,
getSignedDeploymentUrlAsync,
} from '../../worker/deployment';
import { UploadParams, batchUploadAsync, uploadAsync } from '../../worker/upload';
import {
UploadParams,
batchUploadAsync,
callUploadApiAsync,
uploadAsync,
} from '../../worker/upload';
import {
formatWorkerDeploymentJson,
formatWorkerDeploymentTable,
@@ -53,6 +55,13 @@ interface RawDeployFlags {
'export-dir': string;
}
interface DeployInProgressParams {
id: string;
fullName: string;
baseURL: string;
token: string;
}
export default class WorkerDeploy extends EasCommand {
static override description = 'Deploy your Expo web build';
static override aliases = ['deploy'];
@@ -129,7 +138,24 @@ export default class WorkerDeploy extends EasCommand {
}
}
async function uploadTarballAsync(tarPath: string, uploadUrl: string): Promise<any> {
async function finalizeDeployAsync(deployParams: DeployInProgressParams): Promise<void> {
const finalizeDeployUrl = new URL('/deploy/finalize', deployParams.baseURL);
finalizeDeployUrl.searchParams.set('token', deployParams.token);
const result = await callUploadApiAsync(finalizeDeployUrl, {
method: 'POST',
headers: {
accept: 'application/json',
},
});
if (!result || typeof result !== 'object' || !('success' in result) || !result.success) {
throw new Error('Deploy failed: Incomplete asset uploads. Please try again');
}
}
async function uploadTarballAsync(
tarPath: string,
uploadUrl: string
): Promise<DeployInProgressParams> {
const { response } = await uploadAsync({
url: uploadUrl,
filePath: tarPath,
@@ -153,26 +179,33 @@ export default class WorkerDeploy extends EasCommand {
if (!json.success || !json.result || typeof json.result !== 'object') {
throw new Error(json.message ? `Upload failed: ${json.message}` : 'Upload failed!');
}
return json.result;
const { id, fullName, token } = json.result;
if (typeof token !== 'string') {
throw new Error('Upload failed: API failed to return a deployment token');
} else if (typeof id !== 'string') {
throw new Error('Upload failed: API failed to return a deployment identifier');
} else if (typeof fullName !== 'string') {
throw new Error('Upload failed: API failed to return a script name');
}
const baseURL = new URL('/', uploadUrl).toString();
return { id, fullName, baseURL, token };
}
}
async function uploadAssetsAsync(
assetMap: WorkerAssets.AssetMap,
uploads: Record<string, string>
deployParams: DeployInProgressParams
): Promise<void> {
if (typeof uploads !== 'object' || !uploads) {
const uploadParams: UploadParams[] = [];
const assetPath = projectDist.type === 'server' ? projectDist.clientPath : projectDist.path;
if (!assetPath) {
return;
}
// TODO(@kitten): Batch and upload multiple files in parallel
const uploadParams: UploadParams[] = [];
const assetPath = projectDist.type === 'server' ? projectDist.clientPath : projectDist.path;
for await (const asset of WorkerAssets.listAssetMapFilesAsync(assetPath, assetMap)) {
const uploadURL = uploads[asset.normalizedPath];
if (uploadURL) {
uploadParams.push({ url: uploadURL, filePath: asset.path });
}
const uploadURL = new URL(`/asset/${asset.sha512}`, deployParams.baseURL);
uploadURL.searchParams.set('token', deployParams.token);
uploadParams.push({ url: uploadURL.toString(), filePath: asset.path });
}
const progress = {
@@ -213,7 +246,7 @@ export default class WorkerDeploy extends EasCommand {
let assetMap: WorkerAssets.AssetMap;
let tarPath: string;
let deployResult: any;
let deployResult: DeployInProgressParams;
let progress = ora('Preparing project').start();
try {
@@ -252,7 +285,8 @@ export default class WorkerDeploy extends EasCommand {
throw error;
}
await uploadAssetsAsync(assetMap, deployResult.uploads);
await uploadAssetsAsync(assetMap, deployResult);
await finalizeDeployAsync(deployResult);
let deploymentAlias: null | Awaited<ReturnType<typeof assignWorkerDeploymentAliasAsync>> = null;
if (flags.aliasName) {
@@ -311,7 +345,7 @@ export default class WorkerDeploy extends EasCommand {
deploymentIdentifier: deployResult.id,
url: getDeploymentUrlFromFullName(deployResult.fullName),
},
aliases: [deploymentAlias].filter(Boolean) as WorkerDeploymentAliasFragment[],
aliases: [deploymentAlias],
production: deploymentProdAlias,
})
);
@@ -328,7 +362,7 @@ export default class WorkerDeploy extends EasCommand {
deploymentIdentifier: deployResult.id,
url: getDeploymentUrlFromFullName(deployResult.fullName),
},
aliases: [deploymentAlias].filter(Boolean) as WorkerDeploymentAliasFragment[],
aliases: [deploymentAlias],
production: deploymentProdAlias,
})
);
@@ -362,36 +396,36 @@ async function resolveExportedProjectAsync(
modifiedAt: Date | null;
path: string;
serverPath: string;
clientPath: string;
clientPath?: string;
}
> {
const exportPath = path.join(projectDir, flags.exportDir);
const serverPath = path.join(exportPath, 'server');
const clientPath = path.join(exportPath, 'client');
const [hasServerPath, hasClientPath, exportStat] = await Promise.all([
isDirectory(serverPath),
isDirectory(clientPath),
const [exportDirStat, expoRoutesStat, hasClientDir] = await Promise.all([
fs.promises.stat(exportPath).catch(() => null),
fs.promises.stat(path.join(serverPath, '_expo/routes.json')).catch(() => null),
isDirectory(clientPath),
]);
if (!exportStat?.isDirectory()) {
if (!exportDirStat?.isDirectory()) {
throw new Error(
`No "${flags.exportDir}/" folder found. Prepare your project for deployment with "npx expo export --platform web"`
);
}
if (hasServerPath && hasClientPath) {
if (expoRoutesStat?.isFile()) {
return {
type: 'server',
path: exportPath,
modifiedAt: exportStat.mtime,
modifiedAt: exportDirStat.mtime,
serverPath,
clientPath,
clientPath: hasClientDir ? clientPath : undefined,
};
}
return { type: 'static', path: exportPath, modifiedAt: exportStat.mtime };
return { type: 'static', path: exportPath, modifiedAt: exportDirStat.mtime };
}
function logExportedProjectInfo(
@@ -36,6 +36,7 @@ export enum AndroidActionType {
UpdateCredentialsJson,
SetUpBuildCredentialsFromCredentialsJson,
SetUpBuildCredentials,
Exit,
}
export enum IosActionType {
@@ -60,4 +61,5 @@ export enum IosActionType {
UseExistingAscApiKeyForSubmissions,
CreateAscApiKeyForSubmissions,
RemoveAscApiKey,
Exit,
}
@@ -26,6 +26,11 @@ export const highLevelActions: ActionInfo[] = [
title: 'Go back',
scope: Scope.Manager,
},
{
value: AndroidActionType.Exit,
title: 'Exit',
scope: Scope.Manager,
},
];
export const credentialsJsonActions: ActionInfo[] = [
@@ -27,6 +27,11 @@ export const highLevelActions: ActionInfo[] = [
title: 'Go back',
scope: Scope.Manager,
},
{
value: IosActionType.Exit,
title: 'Exit',
scope: Scope.Manager,
},
];
export const credentialsJsonActions: ActionInfo[] = [
@@ -145,6 +145,8 @@ export class ManageAndroid {
} else if (chosenAction === AndroidActionType.GoBackToCaller) {
await this.callingAction.runAsync(ctx);
return;
} else if (chosenAction === AndroidActionType.Exit) {
return;
}
}
@@ -154,6 +154,8 @@ export class ManageIos {
} else if (chosenAction === IosActionType.GoBackToCaller) {
await this.callingAction.runAsync(ctx);
return;
} else if (chosenAction === IosActionType.Exit) {
return;
}
} else if (actionInfo.scope === Scope.Project) {
assert(
+19 -7
View File
@@ -3579,6 +3579,12 @@ export type DeleteWebhookResult = {
id: Scalars['ID']['output'];
};
export type DeleteWorkerDeploymentResult = {
__typename?: 'DeleteWorkerDeploymentResult';
deploymentIdentifier: Scalars['WorkerDeploymentIdentifier']['output'];
id: Scalars['ID']['output'];
};
export type DeployServerlessFunctionResult = {
__typename?: 'DeployServerlessFunctionResult';
url: Scalars['String']['output'];
@@ -3724,6 +3730,7 @@ export type DeploymentsMutation = {
/** Create a signed deployment URL */
createSignedDeploymentUrl: DeploymentSignedUrlResult;
deleteAlias: DeleteAliasResult;
deleteWorkerDeployment: DeleteWorkerDeploymentResult;
};
@@ -3745,6 +3752,11 @@ export type DeploymentsMutationDeleteAliasArgs = {
appId: Scalars['ID']['input'];
};
export type DeploymentsMutationDeleteWorkerDeploymentArgs = {
workerDeploymentId: Scalars['ID']['input'];
};
export type DiscordUser = {
__typename?: 'DiscordUser';
discordIdentifier: Scalars['String']['output'];
@@ -8459,7 +8471,7 @@ export type CreateAndroidSubmissionMutationVariables = Exact<{
}>;
export type CreateAndroidSubmissionMutation = { __typename?: 'RootMutation', submission: { __typename?: 'SubmissionMutation', createAndroidSubmission: { __typename?: 'CreateSubmissionResult', submission: { __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logsUrl?: string | null, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null } } } };
export type CreateAndroidSubmissionMutation = { __typename?: 'RootMutation', submission: { __typename?: 'SubmissionMutation', createAndroidSubmission: { __typename?: 'CreateSubmissionResult', submission: { __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logFiles: Array<string>, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null } } } };
export type CreateIosSubmissionMutationVariables = Exact<{
appId: Scalars['ID']['input'];
@@ -8469,7 +8481,7 @@ export type CreateIosSubmissionMutationVariables = Exact<{
}>;
export type CreateIosSubmissionMutation = { __typename?: 'RootMutation', submission: { __typename?: 'SubmissionMutation', createIosSubmission: { __typename?: 'CreateSubmissionResult', submission: { __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logsUrl?: string | null, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null } } } };
export type CreateIosSubmissionMutation = { __typename?: 'RootMutation', submission: { __typename?: 'SubmissionMutation', createIosSubmission: { __typename?: 'CreateSubmissionResult', submission: { __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logFiles: Array<string>, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null } } } };
export type CreateUploadSessionMutationVariables = Exact<{
type: UploadSessionType;
@@ -8598,7 +8610,7 @@ export type BuildsWithSubmissionsByIdQueryVariables = Exact<{
}>;
export type BuildsWithSubmissionsByIdQuery = { __typename?: 'RootQuery', builds: { __typename?: 'BuildQuery', byId: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, expirationDate?: any | null, isForIosSimulator: boolean, submissions: Array<{ __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logsUrl?: string | null, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null }>, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } } } };
export type BuildsWithSubmissionsByIdQuery = { __typename?: 'RootQuery', builds: { __typename?: 'BuildQuery', byId: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, expirationDate?: any | null, isForIosSimulator: boolean, submissions: Array<{ __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logFiles: Array<string>, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null }>, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } } } };
export type ViewBuildsOnAppQueryVariables = Exact<{
appId: Scalars['String']['input'];
@@ -8726,7 +8738,7 @@ export type SubmissionsByIdQueryVariables = Exact<{
}>;
export type SubmissionsByIdQuery = { __typename?: 'RootQuery', submissions: { __typename?: 'SubmissionQuery', byId: { __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logsUrl?: string | null, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null } } };
export type SubmissionsByIdQuery = { __typename?: 'RootQuery', submissions: { __typename?: 'SubmissionQuery', byId: { __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logFiles: Array<string>, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null } } };
export type GetAllSubmissionsForAppQueryVariables = Exact<{
appId: Scalars['String']['input'];
@@ -8737,7 +8749,7 @@ export type GetAllSubmissionsForAppQueryVariables = Exact<{
}>;
export type GetAllSubmissionsForAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, submissions: Array<{ __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logsUrl?: string | null, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null }> } } };
export type GetAllSubmissionsForAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, submissions: Array<{ __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logFiles: Array<string>, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null }> } } };
export type ViewUpdatesByGroupQueryVariables = Exact<{
groupId: Scalars['ID']['input'];
@@ -8793,7 +8805,7 @@ export type AppFragment = { __typename?: 'App', id: string, name: string, fullNa
export type BuildFragment = { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, expirationDate?: any | null, isForIosSimulator: boolean, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } };
export type BuildWithSubmissionsFragment = { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, expirationDate?: any | null, isForIosSimulator: boolean, submissions: Array<{ __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logsUrl?: string | null, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null }>, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } };
export type BuildWithSubmissionsFragment = { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, expirationDate?: any | null, isForIosSimulator: boolean, submissions: Array<{ __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logFiles: Array<string>, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null }>, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } };
export type EnvironmentSecretFragment = { __typename?: 'EnvironmentSecret', id: string, name: string, type: EnvironmentSecretType, createdAt: any };
@@ -8803,7 +8815,7 @@ export type RuntimeFragment = { __typename?: 'Runtime', id: string, version: str
export type StatuspageServiceFragment = { __typename?: 'StatuspageService', id: string, name: StatuspageServiceName, status: StatuspageServiceStatus, incidents: Array<{ __typename?: 'StatuspageIncident', id: string, status: StatuspageIncidentStatus, name: string, impact: StatuspageIncidentImpact, shortlink: string }> };
export type SubmissionFragment = { __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logsUrl?: string | null, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null };
export type SubmissionFragment = { __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logFiles: Array<string>, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null };
export type UpdateFragment = { __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null };
@@ -28,6 +28,6 @@ export const SubmissionFragmentNode = gql`
errorCode
message
}
logsUrl
logFiles
}
`;
+7 -2
View File
@@ -31,7 +31,7 @@ import { PublishQuery } from '../graphql/queries/PublishQuery';
import Log, { learnMore } from '../log';
import { RequestedPlatform, requestedPlatformDisplayNames } from '../platform';
import { promptAsync } from '../prompts';
import { getBranchNameFromChannelNameAsync } from '../update/getBranchNameFromChannelNameAsync';
import { getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync } from '../update/getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync';
import {
UpdateJsonInfo,
formatUpdateMessage,
@@ -598,7 +598,12 @@ export async function getBranchNameForCommandAsync({
}
if (channelNameArg) {
return await getBranchNameFromChannelNameAsync(graphqlClient, projectId, channelNameArg);
const { branchName } = await getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync(
graphqlClient,
projectId,
channelNameArg
);
return branchName;
}
if (branchNameArg) {
+14 -15
View File
@@ -22,21 +22,20 @@ export async function displayLogsAsync(
}
async function downloadAndPrintSubmissionLogsAsync(submission: SubmissionFragment): Promise<void> {
if (!submission.logsUrl) {
return;
}
const response = await fetch(submission.logsUrl);
const logs = parseLogs(await response.text());
Log.addNewLineIfNone();
const prefix = chalk.blueBright('[logs] ');
for (const { level, msg } of logs) {
const msgWithPrefix = `${prefix}${msg}`;
if (level === 'error') {
Log.error(msgWithPrefix);
} else if (level === 'warn') {
Log.warn(msgWithPrefix);
} else {
Log.log(msgWithPrefix);
for (const logFile of submission.logFiles) {
const response = await fetch(logFile);
const logs = parseLogs(await response.text());
Log.addNewLineIfNone();
const prefix = chalk.blueBright('[logs] ');
for (const { level, msg } of logs) {
const msgWithPrefix = `${prefix}${msg}`;
if (level === 'error') {
Log.error(msgWithPrefix);
} else if (level === 'warn') {
Log.warn(msgWithPrefix);
} else {
Log.log(msgWithPrefix);
}
}
}
}
@@ -10,12 +10,12 @@ import {
UpdateInsights,
} from '../../graphql/generated';
import { ChannelQuery } from '../../graphql/queries/ChannelQuery';
import { getBranchNameFromChannelNameAsync } from '../getBranchNameFromChannelNameAsync';
import { getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync } from '../getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync';
jest.mock('../../graphql/queries/ChannelQuery');
jest.mock('../../graphql/queries/BranchQuery');
describe(getBranchNameFromChannelNameAsync, () => {
describe(getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync, () => {
beforeEach(() => {
jest.resetAllMocks();
});
@@ -30,13 +30,14 @@ describe(getBranchNameFromChannelNameAsync, () => {
}) as any
);
const result = await getBranchNameFromChannelNameAsync(
const result = await getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync(
graphqlClient,
'test-project-id',
'channel-name'
);
expect(result).toBe('test-branch-name');
expect(result.branchId).toBeTruthy();
expect(result.branchName).toBe('test-branch-name');
});
test('errors when no branch is connected to channel', async () => {
@@ -49,7 +50,11 @@ describe(getBranchNameFromChannelNameAsync, () => {
);
await expect(
getBranchNameFromChannelNameAsync(graphqlClient, 'test-project-id', 'test-channel-name')
getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync(
graphqlClient,
'test-project-id',
'test-channel-name'
)
).rejects.toThrow(
"Channel has no branches associated with it. Run 'eas channel:edit' to map a branch"
);
@@ -66,7 +71,11 @@ describe(getBranchNameFromChannelNameAsync, () => {
);
await expect(
getBranchNameFromChannelNameAsync(graphqlClient, 'test-project-id', 'test-channel-name')
getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync(
graphqlClient,
'test-project-id',
'test-channel-name'
)
).rejects.toThrow(
"Channel has multiple branches associated with it. Instead, use '--branch' instead of '--channel'"
);
@@ -82,13 +91,13 @@ describe(getBranchNameFromChannelNameAsync, () => {
}) as any
);
const result = await getBranchNameFromChannelNameAsync(
const result = await getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync(
graphqlClient,
'test-project-id',
'test-channel-name'
);
expect(result).toBe('test-branch-name');
expect(result.branchName).toBe('test-branch-name');
});
});
@@ -4,12 +4,12 @@ import { createChannelOnAppAsync } from '../channel/queries';
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
import { ChannelQuery } from '../graphql/queries/ChannelQuery';
export async function getBranchNameFromChannelNameAsync(
export async function getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync(
graphqlClient: ExpoGraphqlClient,
projectId: string,
channelName: string
): Promise<string> {
let branchName;
): Promise<{ branchName: string; branchId: string }> {
let branchInfo: { branchName: string; branchId: string };
try {
const channel = await ChannelQuery.viewUpdateChannelAsync(graphqlClient, {
@@ -18,7 +18,8 @@ export async function getBranchNameFromChannelNameAsync(
});
if (channel.updateBranches.length === 1) {
branchName = channel.updateBranches[0].name;
const branch = channel.updateBranches[0];
branchInfo = { branchId: branch.id, branchName: branch.name };
} else if (channel.updateBranches.length === 0) {
throw new Error(
"Channel has no branches associated with it. Run 'eas channel:edit' to map a branch"
@@ -51,8 +52,8 @@ export async function getBranchNameFromChannelNameAsync(
);
}
branchName = channelName;
branchInfo = { branchId, branchName: channelName };
}
return branchName;
return branchInfo;
}
+12 -2
View File
@@ -58,7 +58,10 @@ export async function republishAsync({
update.branchId === arbitraryUpdate.branchId &&
update.branchName === arbitraryUpdate.branchName &&
update.runtimeVersion === arbitraryUpdate.runtimeVersion;
assert(updatesToPublish.every(isSameGroup), 'All updates must belong to the same update group');
assert(
updatesToPublish.every(isSameGroup),
'All updates being republished must belong to the same update group'
);
assert(
updatesToPublish.every(u => u.isRollBackToEmbedded) ||
@@ -66,6 +69,11 @@ export async function republishAsync({
'All updates must either be roll back to embedded updates or not'
);
assert(
!updatesToPublish.some(u => !!u.rolloutControlUpdate),
'Cannot republish an update that is being rolled-out. Either complete the update rollout and then republish or publish a new rollout update.'
);
const { runtimeVersion } = arbitraryUpdate;
// If codesigning was created for the original update, we need to add it to the republish.
@@ -90,7 +98,9 @@ export async function republishAsync({
}
}
Log.withTick(`The republished update group will be signed`);
Log.withTick(
`The republished update group will be signed with the same code signing key and algorithm as the original update`
);
}
const publishIndicator = ora('Republishing...').start();
+4 -3
View File
@@ -12,11 +12,12 @@ export async function promptVariableEnvironmentAsync(
);
}
return await selectAsync('Select environment:', [
{ title: 'Development', value: EnvironmentVariableEnvironment.Development },
{ title: 'Preview', value: EnvironmentVariableEnvironment.Preview },
{ title: 'Production', value: EnvironmentVariableEnvironment.Production },
{ title: 'development', value: EnvironmentVariableEnvironment.Development },
{ title: 'preview', value: EnvironmentVariableEnvironment.Preview },
{ title: 'production', value: EnvironmentVariableEnvironment.Production },
]);
}
export async function promptVariableValueAsync({
nonInteractive,
required = true,
+13 -6
View File
@@ -82,12 +82,14 @@ export type AssetMap = Record<string, string>;
/** Creates an asset map of a given target path */
async function createAssetMapAsync(
assetPath: string,
assetPath?: string,
options?: AssetMapOptions
): Promise<AssetMap> {
const map: AssetMap = Object.create(null);
for await (const file of listFilesRecursively(assetPath)) {
map[file.normalizedPath] = await computeSha512HashAsync(file.path, options?.hashOptions);
if (assetPath) {
for await (const file of listFilesRecursively(assetPath)) {
map[file.normalizedPath] = await computeSha512HashAsync(file.path, options?.hashOptions);
}
}
return map;
}
@@ -142,18 +144,23 @@ async function* listWorkerFilesAsync(workerPath: string): AsyncGenerator<WorkerF
}
}
interface AssetFileEntry {
normalizedPath: string;
sha512: string;
path: string;
}
/** Reads files of an asset maps and enumerates normalized paths and data */
async function* listAssetMapFilesAsync(
assetPath: string,
assetMap: AssetMap
): AsyncGenerator<WorkerFileEntry> {
): AsyncGenerator<AssetFileEntry> {
for (const normalizedPath in assetMap) {
const filePath = path.resolve(assetPath, normalizedPath.split('/').join(path.sep));
const data = await fs.promises.readFile(filePath);
yield {
normalizedPath,
path: filePath,
data,
sha512: assetMap[normalizedPath],
};
}
}
+47 -42
View File
@@ -32,32 +32,21 @@ export async function getSignedDeploymentUrlAsync(
['APP_NO_DEV_DOMAIN_NAME'].includes(e?.extensions?.errorCode as string)
);
// Throw unexpected errors eagerly
if (!isMissingDevDomain) {
throw error;
}
if (options.nonInteractive) {
throw new Error(
'The project URL needs to be set up, but the terminal is running in non-interactive mode.'
);
}
const suggestedDevDomainName = await DeploymentsQuery.getSuggestedDevDomainByAppIdAsync(
graphqlClient,
{ appId: options.appId }
);
// Ensure the callback is invoked, containing cleanup logic for possible spinners
options.onSetupDevDomain?.();
await chooseDevDomainNameAsync({
// Assign the dev domain name by prompting the user
await assignDevDomainNameAsync({
graphqlClient,
appId: options.appId,
initial: suggestedDevDomainName,
});
return await DeploymentsMutation.createSignedDeploymentUrlAsync(graphqlClient, {
appId: options.appId,
deploymentIdentifier: options.deploymentIdentifier,
nonInteractive: options.nonInteractive,
});
// Retry creating the signed URL
return await getSignedDeploymentUrlAsync(graphqlClient, options);
}
}
@@ -89,15 +78,7 @@ function formatDevDomainName(name = ''): string {
.trim();
}
async function chooseDevDomainNameAsync({
graphqlClient,
appId,
initial,
}: {
graphqlClient: ExpoGraphqlClient;
appId: string;
initial: string;
}): Promise<void> {
async function promptDevDomainNameAsync(initialDevDomain: string): Promise<string> {
const rootDomain = `.${EXPO_BASE_DOMAIN}.app`;
const memoizedFormatDevDomainName = memoize(formatDevDomainName);
@@ -105,7 +86,7 @@ async function chooseDevDomainNameAsync({
type: 'text',
name: 'name',
message: 'Choose a preview URL for your project:',
initial,
initial: initialDevDomain,
validate: (value: string) => {
if (!value) {
return 'You have to choose a preview URL for your project';
@@ -138,32 +119,56 @@ async function chooseDevDomainNameAsync({
},
});
// This should never happen due to the validation, if it does its an error
if (!name) {
throw new Error('No preview URL provided, aborting deployment.');
}
try {
const success = await DeploymentsMutation.assignDevDomainNameAsync(graphqlClient, {
appId,
name,
});
return name;
}
if (!success) {
throw new Error('Failed to assign preview URL');
}
} catch (error: any) {
/**
* Assign a dev domain name to a project.
* - When running in interactive mode, it will prompt the user with a suggested domain name.
* - When running in non interactive mode, it will auto-assign the suggested domain name.
*/
export async function assignDevDomainNameAsync({
graphqlClient,
appId,
nonInteractive,
}: {
graphqlClient: ExpoGraphqlClient;
appId: string;
nonInteractive?: boolean;
}): ReturnType<typeof DeploymentsMutation.assignDevDomainNameAsync> {
let devDomainName = await DeploymentsQuery.getSuggestedDevDomainByAppIdAsync(graphqlClient, {
appId,
});
if (!nonInteractive) {
devDomainName = await promptDevDomainNameAsync(devDomainName);
}
try {
return await DeploymentsMutation.assignDevDomainNameAsync(graphqlClient, {
appId,
name: devDomainName,
});
} catch (error) {
const isChosenNameTaken = (error as GraphqlError)?.graphQLErrors?.some(e =>
['DEV_DOMAIN_NAME_TAKEN'].includes(e?.extensions?.errorCode as string)
);
if (isChosenNameTaken) {
Log.error(`The preview URL "${name}" is already taken, choose a different URL.`);
await chooseDevDomainNameAsync({ graphqlClient, appId, initial });
}
// Throw unexpected errors eagerly
if (!isChosenNameTaken) {
throw error;
}
if (!nonInteractive) {
Log.error(`The preview URL "${devDomainName}" is already taken, choose a different URL.`);
}
return await assignDevDomainNameAsync({ graphqlClient, appId, nonInteractive });
}
}
+27 -5
View File
@@ -139,6 +139,28 @@ export async function uploadAsync(params: UploadParams): Promise<UploadResult> {
);
}
export async function callUploadApiAsync(url: string | URL, init?: RequestInit): Promise<unknown> {
return await promiseRetry(async retry => {
let response: Response;
try {
response = await fetch(url, {
...init,
agent: getAgent(),
});
} catch (error) {
return retry(error);
}
if (response.status >= 500 && response.status <= 599) {
retry(new Error(`Deployment failed: ${response.statusText}`));
}
try {
return await response.json();
} catch (error) {
retry(error);
}
});
}
export interface UploadPending {
params: UploadParams;
}
@@ -165,13 +187,13 @@ export async function* batchUploadAsync(
}
yield await Promise.race(queue);
}
} catch (error: any) {
if (typeof error !== 'object' || error.name !== 'AbortError') {
throw error;
}
} finally {
if (queue.size > 0) {
controller.abort();
}
} catch (error: any) {
if (error.name !== 'AbortError') {
throw error;
}
}
}
+28 -26
View File
@@ -22,7 +22,7 @@ type WorkerDeploymentData = {
/** The actual deployment information */
deployment: Pick<WorkerDeploymentFragment, 'deploymentIdentifier' | 'url'>;
/** All modified aliases of the deployment, if any */
aliases?: WorkerDeploymentAliasFragment[];
aliases?: (WorkerDeploymentAliasFragment | null)[];
/** The production promoting alias of the deployment, if any */
production?: WorkerDeploymentAliasFragment | null;
};
@@ -34,7 +34,10 @@ export function formatWorkerDeploymentTable(data: WorkerDeploymentData): string
];
if (data.aliases?.length) {
fields.push({ label: 'Alias URL', value: data.aliases[0].url });
const alias = data.aliases.filter(Boolean)[0];
if (alias) {
fields.push({ label: 'Alias URL', value: alias.url });
}
}
if (data.production) {
fields.push({ label: 'Production URL', value: data.production.url });
@@ -49,34 +52,33 @@ export function formatWorkerDeploymentTable(data: WorkerDeploymentData): string
type WorkerDeploymentOutput = {
/** The absolute URL to the dashboard on `expo.dev` */
dashboardUrl: string;
/** The deployment information */
deployment: {
identifier: string;
url: string;
aliases?: { id: string; name: string; url: string }[];
production?: { id: string; url: string };
};
/** The deployment identifier */
identifier: string;
/** The deployment URL */
url: string;
/** Custom aliases, if assigned */
aliases?: { id: string; url: string; name: string }[];
/** The production alias, if assigned */
production?: { id: string; url: string };
};
export function formatWorkerDeploymentJson(data: WorkerDeploymentData): WorkerDeploymentOutput {
const aliases = !data.aliases
? []
: (data.aliases.filter(Boolean) as WorkerDeploymentAliasFragment[]);
return {
dashboardUrl: getDashboardUrl(data.projectId),
deployment: {
identifier: data.deployment.deploymentIdentifier,
url: data.deployment.url,
aliases: !data.aliases?.length
? undefined
: data.aliases.map(alias => ({
id: alias.id,
name: alias.aliasName,
url: alias.url,
})),
production: !data.production
? undefined
: {
id: data.production.id,
url: data.production.url,
},
},
identifier: data.deployment.deploymentIdentifier,
url: data.deployment.url,
aliases: !aliases.length
? undefined
: aliases.map(alias => ({ id: alias.id, url: alias.url, name: alias.aliasName })),
production: !data.production
? undefined
: {
id: data.production.id,
url: data.production.url,
},
};
}