mirror of
https://github.com/expo/eas-cli.git
synced 2026-11-15 03:38:08 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f46063cca5 | ||
|
|
c0cfa93b69 | ||
|
|
7d6f620f91 | ||
|
|
c973a1f603 | ||
|
|
1b8f60fad4 | ||
|
|
7a30de9ad7 | ||
|
|
4247b65e09 | ||
|
|
8c388d5173 | ||
|
|
fce945679f | ||
|
|
7772e199b4 | ||
|
|
755e105252 | ||
|
|
611d0c98ee | ||
|
|
949a90187b | ||
|
|
bb14d9255a | ||
|
|
98e35926ff | ||
|
|
cd433405cb | ||
|
|
3ad54b0fc9 | ||
|
|
5184117ed6 | ||
|
|
868df87146 | ||
|
|
2f0cc2361b | ||
|
|
4be6c51418 | ||
|
|
99c4c618c9 | ||
|
|
742a1a05e5 | ||
|
|
6f806cabb1 | ||
|
|
4c84794a31 | ||
|
|
a1ab5a4fb5 | ||
|
|
dc11c1c487 | ||
|
|
805865356c | ||
|
|
5fc0757fb0 | ||
|
|
2c6d92745f | ||
|
|
f677e038cf | ||
|
|
ef13c2bf0e | ||
|
|
68e552010e | ||
|
|
c5143fabad | ||
|
|
64efdad61d | ||
|
|
8bc07ca452 | ||
|
|
ea4d28e7d9 | ||
|
|
e1fce4a066 | ||
|
|
76d75e9c17 | ||
|
|
9278b3c17d | ||
|
|
ef9fbe84c0 | ||
|
|
b3a69e8863 | ||
|
|
5e4663ac44 | ||
|
|
ca18a555c1 | ||
|
|
c446bbb016 | ||
|
|
d5254434c6 | ||
|
|
e2277b9482 | ||
|
|
739502aef9 | ||
|
|
de42624992 |
No files matched your search
@@ -14,6 +14,11 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: If you leave out sections there is a high likelihood your issue will be closed. If you have a question, not a bug report, please post it on our [forums](https://forums.expo.dev/) instead.
|
||||
- type: input
|
||||
attributes:
|
||||
label: Build/Submit details page URL
|
||||
description: If you're reporting an issue with EAS Build and/or EAS Submit, please provide the URL to the details page URL. The page can be only viewed by the Expo team members. Providing the URL is optional but it makes debugging the issue easier.
|
||||
placeholder: https://expo.dev/accounts/ACCOUNT_NAME/projects/PROJECT_NAME/builds/BUILD_ID
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
@@ -21,19 +26,18 @@ body:
|
||||
label: Summary
|
||||
description: Describe the issue in 1 or 2 sentences
|
||||
placeholder: Clearly describe what the expected behavior is vs. what is actually happening. This should be as short as possible, while still communicating all the necessary information. If your summary is just 'X library/method isn't working', then you need to continue debugging yourself and provide more information.
|
||||
- type: textarea
|
||||
- type: input
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: Managed or bare?
|
||||
description: See the [Workflows](https://docs.expo.dev/introduction/managed-vs-bare/) page for more information.
|
||||
placeholder: Is your project managed or bare? Bare - Android and/or iOS native projects exist in your repo; Managed - you don't have native code (custom or 3rd party) in your project.
|
||||
description: Is your project managed or bare? Bare - Android and/or iOS native projects exist in your repo; Managed - you don't have native code (custom or 3rd party) in your project. See the [Workflows](https://docs.expo.dev/introduction/managed-vs-bare/) page for more information.
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: Environment
|
||||
placeholder: Run `eas diagnostics` and paste the output here
|
||||
description: Run `eas diagnostics` and paste the output here.
|
||||
- type: textarea
|
||||
validations:
|
||||
required: false
|
||||
|
||||
@@ -15,4 +15,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: bash bin/install.sh
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- run: eas --version
|
||||
@@ -32,15 +32,23 @@ jobs:
|
||||
- run: yarn build
|
||||
- name: Build tarballs
|
||||
working-directory: ${{ github.workspace }}/packages/eas-cli
|
||||
run: yarn oclif-dev pack --targets linux-x64,linux-arm
|
||||
run: |
|
||||
yarn pretarball-ci
|
||||
yarn oclif pack:tarballs --no-xz --targets linux-x64,linux-arm
|
||||
- id: x64
|
||||
run: echo "::set-output name=filename::$(ls eas-*-x64.tar.gz)"
|
||||
working-directory: ${{ github.workspace }}/packages/eas-cli/dist
|
||||
- id: arm
|
||||
run: echo "::set-output name=filename::$(ls eas-*-arm.tar.gz)"
|
||||
working-directory: ${{ github.workspace }}/packages/eas-cli/dist
|
||||
- name: Upload linux-x64 tarball
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.release.outputs.upload_url }}
|
||||
asset_path: packages/eas-cli/dist/eas-linux-x64.tar.gz
|
||||
asset_name: eas-linux-x64.tar.gz
|
||||
asset_path: packages/eas-cli/dist/${{ steps.x64.outputs.filename }}
|
||||
asset_name: ${{ steps.x64.outputs.filename }}
|
||||
asset_content_type: application/gzip
|
||||
- name: Upload linux-arm tarball
|
||||
uses: actions/upload-release-asset@v1
|
||||
@@ -48,8 +56,8 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.release.outputs.upload_url }}
|
||||
asset_path: packages/eas-cli/dist/eas-linux-arm.tar.gz
|
||||
asset_name: eas-linux-arm.tar.gz
|
||||
asset_path: packages/eas-cli/dist/${{ steps.arm.outputs.filename }}
|
||||
asset_name: ${{ steps.arm.outputs.filename }}
|
||||
asset_content_type: application/gzip
|
||||
build-mac:
|
||||
name: Build for macOS
|
||||
@@ -65,15 +73,20 @@ jobs:
|
||||
- run: yarn build
|
||||
- name: Build tarballs
|
||||
working-directory: ${{ github.workspace }}/packages/eas-cli
|
||||
run: yarn oclif-dev pack --targets darwin-x64
|
||||
run: |
|
||||
yarn pretarball-ci
|
||||
yarn oclif pack:tarballs --no-xz --targets darwin-x64
|
||||
- id: x64
|
||||
run: echo "::set-output name=filename::$(ls eas-*-x64.tar.gz)"
|
||||
working-directory: ${{ github.workspace }}/packages/eas-cli/dist
|
||||
- name: Upload darwin-x64 tarball
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.release.outputs.upload_url }}
|
||||
asset_path: packages/eas-cli/dist/eas-darwin-x64.tar.gz
|
||||
asset_name: eas-darwin-x64.tar.gz
|
||||
asset_path: packages/eas-cli/dist/${{ steps.x64.outputs.filename }}
|
||||
asset_name: ${{ steps.x64.outputs.filename }}
|
||||
asset_content_type: application/gzip
|
||||
build-windows:
|
||||
name: Build for Windows
|
||||
@@ -87,21 +100,23 @@ jobs:
|
||||
- run: yarn install --frozen-lockfile --check-files
|
||||
- run: sudo apt-get install nsis
|
||||
- run: yarn build
|
||||
- run: yarn oclif-dev pack:win
|
||||
- run: |
|
||||
yarn pretarball-ci
|
||||
yarn oclif pack:win
|
||||
working-directory: ${{ github.workspace }}/packages/eas-cli
|
||||
- id: x64
|
||||
run: echo "::set-output name=filename::$(ls eas-*-x64.exe)"
|
||||
working-directory: ${{ github.workspace }}/packages/eas-cli/dist/win
|
||||
working-directory: ${{ github.workspace }}/packages/eas-cli/dist/win32
|
||||
- id: x86
|
||||
run: echo "::set-output name=filename::$(ls eas-*-x86.exe)"
|
||||
working-directory: ${{ github.workspace }}/packages/eas-cli/dist/win
|
||||
working-directory: ${{ github.workspace }}/packages/eas-cli/dist/win32
|
||||
- name: Upload x64 installer
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.release.outputs.upload_url }}
|
||||
asset_path: packages/eas-cli/dist/win/${{ steps.x64.outputs.filename }}
|
||||
asset_path: packages/eas-cli/dist/win32/${{ steps.x64.outputs.filename }}
|
||||
asset_name: ${{ steps.x64.outputs.filename }}
|
||||
asset_content_type: application/gzip
|
||||
- name: Upload x86 installer
|
||||
@@ -110,7 +125,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.release.outputs.upload_url }}
|
||||
asset_path: packages/eas-cli/dist/win/${{ steps.x86.outputs.filename }}
|
||||
asset_path: packages/eas-cli/dist/win32/${{ steps.x86.outputs.filename }}
|
||||
asset_name: ${{ steps.x86.outputs.filename }}
|
||||
asset_content_type: application/gzip
|
||||
publish-to-npm:
|
||||
|
||||
@@ -9,10 +9,12 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '16'
|
||||
node-version: 16
|
||||
- uses: preactjs/compressed-size-action@v2
|
||||
with:
|
||||
build-script: 'build:tarballs:linux'
|
||||
repo-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
pattern: './packages/eas-cli/dist/*.tar.gz'
|
||||
compression: 'none'
|
||||
strip-hash: "v\\d+.\\d+.\\d+-\\w+-"
|
||||
clean-script: 'clean'
|
||||
@@ -1,6 +1,7 @@
|
||||
# Build directories
|
||||
packages/*/build
|
||||
packages/eas-cli/dist
|
||||
packages/eas-cli/tmp
|
||||
|
||||
# Code editors
|
||||
.idea
|
||||
|
||||
@@ -6,6 +6,65 @@ This is the log of notable changes to EAS CLI and related packages.
|
||||
|
||||
### 🛠 Breaking changes
|
||||
|
||||
- No longer enable APNS (iOS Push Notifications) capability by default anymore. ([#797](https://github.com/expo/eas-cli/pull/797) by [@EvanBacon](https://github.com/EvanBacon))
|
||||
- Don't configure Android projects locally. Clean up old Gradle signing config. Streamline `expo-updates` configuration. ([#888](https://github.com/expo/eas-cli/pull/888) by [@dsokal](https://github.com/dsokal))
|
||||
|
||||
### 🎉 New features
|
||||
|
||||
- Add `update:list` command. ([#884](https://github.com/expo/eas-cli/pull/884) by [@jkhales](https://github.com/jkhales))
|
||||
- Improve error message for outdated Apple PLA error. ([#889](https://github.com/expo/eas-cli/pull/889) by [@EvanBacon](https://github.com/EvanBacon))
|
||||
- Add `--output` flag to the build command. ([#885](https://github.com/expo/eas-cli/pull/885) by [@wkozyra95](https://github.com/wkozyra95))
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
- Fix creating project archive with symlink cycle. ([#891](https://github.com/expo/eas-cli/pull/891) by [@wkozyra95](https://github.com/wkozyra95))
|
||||
- Sign Android debug builds with the correct keystore. Previously, all debug builds would be signed with a default debug keystore. ([#888](https://github.com/expo/eas-cli/pull/888) by [@dsokal](https://github.com/dsokal))
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
## [0.43.0](https://github.com/expo/eas-cli/releases/tag/v0.43.0) - 2022-01-03
|
||||
|
||||
### 🎉 New features
|
||||
|
||||
- Add `eas channel:delete`. ([#846](https://github.com/expo/eas-cli/pull/846), [#869](https://github.com/expo/eas-cli/pull/869) by [@jkhales](https://github.com/jkhales))
|
||||
- Add `eas autocomplete`. ([#870](https://github.com/expo/eas-cli/pull/870) by [@dsokal](https://github.com/dsokal))
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
- Fix saving `build:inspect` results to project subdirectory. ([#863](https://github.com/expo/eas-cli/pull/863) by [@wkozyra95](https://github.com/wkozyra95))
|
||||
|
||||
## [0.42.4](https://github.com/expo/eas-cli/releases/tag/v0.42.4) - 2021-12-21
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
- Add missing dependency - `@oclif/plugin-help`. ([#865](https://github.com/expo/eas-cli/pull/865) by [@dsokal](https://github.com/dsokal))
|
||||
|
||||
## [0.42.3](https://github.com/expo/eas-cli/releases/tag/v0.42.3) - 2021-12-21
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
- Allow select eas commands to be run outside of a project. ([#851](https://github.com/expo/eas-cli/pull/851) by [@jkhales](https://github.com/jkhales))
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
- Replace all oclif dependencies with `@oclif/core`. ([#858](https://github.com/expo/eas-cli/pull/858) by [@dsokal](https://github.com/dsokal))
|
||||
|
||||
## [0.41.1](https://github.com/expo/eas-cli/releases/tag/v0.41.1) - 2021-12-16
|
||||
|
||||
### 🎉 New features
|
||||
|
||||
- Adds commands for EAS Update, which is now in preview for subscribers. EAS Update makes fixing small bugs and pushing quick fixes a snap in between app store submissions. It accomplishes this by allowing an end-user's app to swap out the non-native parts of their app (for example, JS, styling, and image changes) with a new update that contains bug fixes and other updates.
|
||||
- Adds `eas update`, which can bundle and publish updates on a branch.
|
||||
- Adds `eas branch`, which manages branches. Branches contain a list of updates and are linked to channels.
|
||||
- Adds `eas channel`, which manages channels. Channels are specified inside builds and are linked to branches, allowing us to link specific updates with specific builds.
|
||||
- Read more in our [feature preview docs](https://docs.expo.dev/eas-update/introduction/).
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
- Fix `eas submit` displaying a prompt in non-interactive mode when some ASC API credentials are missing in `eas.json`. ([#841](https://github.com/expo/eas-cli/pull/841) by [@barthap](https://github.com/barthap))
|
||||
|
||||
## [0.41.0](https://github.com/expo/eas-cli/releases/tag/v0.41.0) - 2021-12-13
|
||||
|
||||
### 🎉 New features
|
||||
|
||||
- Ask user to select profile if `release` does not exist. ([#829](https://github.com/expo/eas-cli/pull/829) by [@dsokal](https://github.com/dsokal))
|
||||
|
||||
+4
-5
@@ -11,7 +11,7 @@
|
||||
|
||||
prefix="${EAS_PREFIX:-/usr/local}"
|
||||
temp_dir="$(mktemp -d)"
|
||||
|
||||
|
||||
if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]
|
||||
then
|
||||
# Use colors when stdout is a terminal and NO_COLOR isn't set.
|
||||
@@ -67,7 +67,7 @@
|
||||
if [[ ! ":$PATH:" == *":$prefix/bin:"* ]]; then
|
||||
abort "Your path is missing $prefix/bin, you need to add this to \$PATH use this installer."
|
||||
fi
|
||||
|
||||
|
||||
hardware="$(uname -m)"
|
||||
case "$hardware" in
|
||||
x86_64)
|
||||
@@ -95,13 +95,12 @@
|
||||
abort "This installer is supported only on macOS, Linux, and Windows Subsystem for Linux."
|
||||
;;
|
||||
esac
|
||||
|
||||
url="https://github.com/expo/eas-cli/releases/latest/download/eas-$platform-$arch.tar.gz"
|
||||
url=$(hub release -L 1 | xargs hub release show --show-downloads | grep "${platform}-${arch}.tar.gz")
|
||||
echo "Installing EAS CLI from $url"
|
||||
|
||||
mkdir -p "$temp_dir"
|
||||
cd "$temp_dir"
|
||||
|
||||
|
||||
echo
|
||||
echo "Downloading..."
|
||||
if [ "$(command -v curl)" ]
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"version": "0.41.0"
|
||||
"version": "0.44.0"
|
||||
}
|
||||
+4
-3
@@ -5,18 +5,18 @@
|
||||
],
|
||||
"scripts": {
|
||||
"build": "lerna run build",
|
||||
"build:tarballs:linux": "yarn build && yarn workspace eas-cli oclif-dev pack --targets linux-x64",
|
||||
"build:tarballs:linux": "yarn build-for-size-check",
|
||||
"build-for-size-check": "yarn build && yarn workspace eas-cli pretarball-ci && CLI_SIZE_CHECK=1 yarn workspace eas-cli oclif pack:tarballs --no-xz --targets linux-x64",
|
||||
"typecheck": "lerna run typecheck",
|
||||
"start": "lerna run watch --parallel",
|
||||
"watch": "yarn start",
|
||||
"eas": "packages/eas-cli/bin/run",
|
||||
"lint": "eslint .",
|
||||
"release": "./scripts/bin/run update-local-plugin && lerna version",
|
||||
"release": "./scripts/bin/run update-local-plugin && lerna version --exact",
|
||||
"test": "jest",
|
||||
"clean": "lerna run clean && rm -rf node_modules coverage"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@expo/oclif-dev-cli": "1.24.0-expo",
|
||||
"@types/jest": "27.0.1",
|
||||
"@types/node": "16.7.8",
|
||||
"eslint": "7.32.0",
|
||||
@@ -26,6 +26,7 @@
|
||||
"jest": "27.1.0",
|
||||
"jest-watch-typeahead": "0.6.4",
|
||||
"lerna": "4.0.0",
|
||||
"oclif": "2.0.1",
|
||||
"prettier": "2.4.1",
|
||||
"ts-jest": "27.0.5",
|
||||
"typescript": "4.5.2"
|
||||
|
||||
+494
-111
@@ -37,12 +37,22 @@ eas --help COMMAND
|
||||
* [`eas account:logout`](#eas-accountlogout)
|
||||
* [`eas account:view`](#eas-accountview)
|
||||
* [`eas analytics [STATUS]`](#eas-analytics-status)
|
||||
* [`eas autocomplete [SHELL]`](#eas-autocomplete-shell)
|
||||
* [`eas branch:create [NAME]`](#eas-branchcreate-name)
|
||||
* [`eas branch:delete [NAME]`](#eas-branchdelete-name)
|
||||
* [`eas branch:list`](#eas-branchlist)
|
||||
* [`eas branch:rename`](#eas-branchrename)
|
||||
* [`eas branch:view [NAME]`](#eas-branchview-name)
|
||||
* [`eas build`](#eas-build)
|
||||
* [`eas build:cancel [BUILD_ID]`](#eas-buildcancel-build_id)
|
||||
* [`eas build:configure`](#eas-buildconfigure)
|
||||
* [`eas build:inspect`](#eas-buildinspect)
|
||||
* [`eas build:list`](#eas-buildlist)
|
||||
* [`eas build:view [BUILD_ID]`](#eas-buildview-build_id)
|
||||
* [`eas channel:create [NAME]`](#eas-channelcreate-name)
|
||||
* [`eas channel:edit [NAME]`](#eas-channeledit-name)
|
||||
* [`eas channel:list`](#eas-channellist)
|
||||
* [`eas channel:view [NAME]`](#eas-channelview-name)
|
||||
* [`eas config`](#eas-config)
|
||||
* [`eas credentials`](#eas-credentials)
|
||||
* [`eas device:create`](#eas-devicecreate)
|
||||
@@ -56,6 +66,11 @@ eas --help COMMAND
|
||||
* [`eas secret:delete`](#eas-secretdelete)
|
||||
* [`eas secret:list`](#eas-secretlist)
|
||||
* [`eas submit`](#eas-submit)
|
||||
* [`eas update`](#eas-update)
|
||||
* [`eas update:configure`](#eas-updateconfigure)
|
||||
* [`eas update:delete GROUPID`](#eas-updatedelete-groupid)
|
||||
* [`eas update:list`](#eas-updatelist)
|
||||
* [`eas update:view GROUPID`](#eas-updateview-groupid)
|
||||
* [`eas webhook:create`](#eas-webhookcreate)
|
||||
* [`eas webhook:delete [ID]`](#eas-webhookdelete-id)
|
||||
* [`eas webhook:list`](#eas-webhooklist)
|
||||
@@ -70,11 +85,14 @@ log in with your Expo account
|
||||
USAGE
|
||||
$ eas account:login
|
||||
|
||||
DESCRIPTION
|
||||
log in with your Expo account
|
||||
|
||||
ALIASES
|
||||
$ eas login
|
||||
```
|
||||
|
||||
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/account/login.ts)_
|
||||
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/account/login.ts)_
|
||||
|
||||
## `eas account:logout`
|
||||
|
||||
@@ -84,11 +102,14 @@ log out
|
||||
USAGE
|
||||
$ eas account:logout
|
||||
|
||||
DESCRIPTION
|
||||
log out
|
||||
|
||||
ALIASES
|
||||
$ eas logout
|
||||
```
|
||||
|
||||
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/account/logout.ts)_
|
||||
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/account/logout.ts)_
|
||||
|
||||
## `eas account:view`
|
||||
|
||||
@@ -98,11 +119,14 @@ show the username you are logged in as
|
||||
USAGE
|
||||
$ eas account:view
|
||||
|
||||
DESCRIPTION
|
||||
show the username you are logged in as
|
||||
|
||||
ALIASES
|
||||
$ eas whoami
|
||||
```
|
||||
|
||||
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/account/view.ts)_
|
||||
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/account/view.ts)_
|
||||
|
||||
## `eas analytics [STATUS]`
|
||||
|
||||
@@ -111,9 +135,137 @@ view or change analytics settings
|
||||
```
|
||||
USAGE
|
||||
$ eas analytics [STATUS]
|
||||
|
||||
DESCRIPTION
|
||||
view or change analytics settings
|
||||
```
|
||||
|
||||
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/analytics.ts)_
|
||||
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/analytics.ts)_
|
||||
|
||||
## `eas autocomplete [SHELL]`
|
||||
|
||||
display autocomplete installation instructions
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas autocomplete [SHELL] [-r]
|
||||
|
||||
ARGUMENTS
|
||||
SHELL shell type
|
||||
|
||||
FLAGS
|
||||
-r, --refresh-cache Refresh cache (ignores displaying instructions)
|
||||
|
||||
DESCRIPTION
|
||||
display autocomplete installation instructions
|
||||
|
||||
EXAMPLES
|
||||
$ eas autocomplete
|
||||
|
||||
$ eas autocomplete bash
|
||||
|
||||
$ eas autocomplete zsh
|
||||
|
||||
$ eas autocomplete --refresh-cache
|
||||
```
|
||||
|
||||
_See code: [@expo/plugin-autocomplete](https://github.com/oclif/plugin-autocomplete/blob/v1.0.2/src/commands/autocomplete/index.ts)_
|
||||
|
||||
## `eas branch:create [NAME]`
|
||||
|
||||
Create a branch on the current project.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas branch:create [NAME] [--json]
|
||||
|
||||
ARGUMENTS
|
||||
NAME Name of the branch to create
|
||||
|
||||
FLAGS
|
||||
--json return a json with the new branch ID and name.
|
||||
|
||||
DESCRIPTION
|
||||
Create a branch on the current project.
|
||||
```
|
||||
|
||||
_See code: [src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/branch/create.ts)_
|
||||
|
||||
## `eas branch:delete [NAME]`
|
||||
|
||||
Delete a branch on the current project
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas branch:delete [NAME] [--json]
|
||||
|
||||
ARGUMENTS
|
||||
NAME Name of the branch to delete
|
||||
|
||||
FLAGS
|
||||
--json return JSON with the edited branch's ID and name.
|
||||
|
||||
DESCRIPTION
|
||||
Delete a branch on the current project
|
||||
```
|
||||
|
||||
_See code: [src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/branch/delete.ts)_
|
||||
|
||||
## `eas branch:list`
|
||||
|
||||
List all branches on this project.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas branch:list [--json]
|
||||
|
||||
FLAGS
|
||||
--json return output as JSON
|
||||
|
||||
DESCRIPTION
|
||||
List all branches on this project.
|
||||
```
|
||||
|
||||
_See code: [src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/branch/list.ts)_
|
||||
|
||||
## `eas branch:rename`
|
||||
|
||||
Rename a branch.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas branch:rename [--from <value>] [--to <value>] [--json]
|
||||
|
||||
FLAGS
|
||||
--from=<value> current name of the branch.
|
||||
--json return a json with the edited branch's ID and name.
|
||||
--to=<value> new name of the branch.
|
||||
|
||||
DESCRIPTION
|
||||
Rename a branch.
|
||||
```
|
||||
|
||||
_See code: [src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/branch/rename.ts)_
|
||||
|
||||
## `eas branch:view [NAME]`
|
||||
|
||||
View a branch.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas branch:view [NAME] [--json]
|
||||
|
||||
ARGUMENTS
|
||||
NAME Name of the branch to view
|
||||
|
||||
FLAGS
|
||||
--json return a json with the branch's ID name and recent update groups.
|
||||
|
||||
DESCRIPTION
|
||||
View a branch.
|
||||
```
|
||||
|
||||
_See code: [src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/branch/view.ts)_
|
||||
|
||||
## `eas build`
|
||||
|
||||
@@ -121,33 +273,30 @@ Start a build
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas build
|
||||
$ eas build [-p android|ios|all] [--json] [--skip-project-configuration] [--profile <value>]
|
||||
[--non-interactive] [--local] [--output <value>] [--wait] [--clear-cache] [--auto-submit |
|
||||
--auto-submit-with-profile <value>]
|
||||
|
||||
OPTIONS
|
||||
FLAGS
|
||||
-p, --platform=(android|ios|all)
|
||||
|
||||
--auto-submit Submit on build complete using the submit profile with the same name as the
|
||||
build profile
|
||||
|
||||
--auto-submit-with-profile=PROFILE_NAME Submit on build complete using the submit profile with provided name
|
||||
|
||||
--clear-cache Clear cache before the build
|
||||
|
||||
--json Enable JSON output, non-JSON messages will be printed to stderr
|
||||
|
||||
--local Run build locally [experimental]
|
||||
|
||||
--non-interactive Run command in non-interactive mode
|
||||
|
||||
--output=<value> Output path for local build
|
||||
--profile=PROFILE_NAME Name of the build profile from eas.json. Defaults to "production" if defined
|
||||
in eas.json.
|
||||
|
||||
--skip-project-configuration Skip project configuration
|
||||
|
||||
--[no-]wait Wait for build(s) to complete
|
||||
|
||||
DESCRIPTION
|
||||
Start a build
|
||||
```
|
||||
|
||||
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/build/index.ts)_
|
||||
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/build/index.ts)_
|
||||
|
||||
## `eas build:cancel [BUILD_ID]`
|
||||
|
||||
@@ -156,9 +305,12 @@ Cancel a build.
|
||||
```
|
||||
USAGE
|
||||
$ eas build:cancel [BUILD_ID]
|
||||
|
||||
DESCRIPTION
|
||||
Cancel a build.
|
||||
```
|
||||
|
||||
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/build/cancel.ts)_
|
||||
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/build/cancel.ts)_
|
||||
|
||||
## `eas build:configure`
|
||||
|
||||
@@ -166,13 +318,16 @@ Configure the project to support EAS Build.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas build:configure
|
||||
$ eas build:configure [-p android|ios|all]
|
||||
|
||||
OPTIONS
|
||||
FLAGS
|
||||
-p, --platform=(android|ios|all) Platform to configure
|
||||
|
||||
DESCRIPTION
|
||||
Configure the project to support EAS Build.
|
||||
```
|
||||
|
||||
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/build/configure.ts)_
|
||||
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/build/configure.ts)_
|
||||
|
||||
## `eas build:inspect`
|
||||
|
||||
@@ -180,31 +335,34 @@ Inspect the state of the project at specific build stages. Useful for troublesho
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas build:inspect
|
||||
$ eas build:inspect -p android|ios -s archive|pre-build|post-build -o <value> [--profile <value>] [--force] [-v]
|
||||
|
||||
FLAGS
|
||||
-o, --output=OUTPUT_DIRECTORY
|
||||
(required) Output directory.
|
||||
|
||||
OPTIONS
|
||||
-p, --platform=(android|ios)
|
||||
(required)
|
||||
|
||||
-s, --stage=(archive|pre-build|post-build)
|
||||
(required) Stage of the build you want to inspect.
|
||||
archive - builds the project archive that would be uploaded to EAS when building
|
||||
pre-build - prepares the project to be built with Gradle/Xcode. Does not run the native build.
|
||||
post-build - builds the native project and leaves the output directory for inspection
|
||||
archive - builds the project archive that would be uploaded to EAS when building
|
||||
pre-build - prepares the project to be built with Gradle/Xcode. Does not run the native build.
|
||||
post-build - builds the native project and leaves the output directory for inspection
|
||||
|
||||
-v, --verbose
|
||||
|
||||
--force
|
||||
Delete OUTPUT_DIRECTORY if it already exists.
|
||||
|
||||
--output=OUTPUT_DIRECTORY
|
||||
(required) Output directory.
|
||||
|
||||
--profile=PROFILE_NAME
|
||||
Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.
|
||||
|
||||
--verbose
|
||||
DESCRIPTION
|
||||
Inspect the state of the project at specific build stages. Useful for troubleshooting.
|
||||
```
|
||||
|
||||
_See code: [src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/build/inspect.ts)_
|
||||
_See code: [src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/build/inspect.ts)_
|
||||
|
||||
## `eas build:list`
|
||||
|
||||
@@ -212,32 +370,32 @@ list all builds for your project
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas build:list
|
||||
$ eas build:list [--platform all|android|ios] [--json] [--status
|
||||
new|in-queue|in-progress|errored|finished|canceled] [--distribution store|internal|simulator] [--channel <value>]
|
||||
[--appVersion <value>] [--appBuildVersion <value>] [--sdkVersion <value>] [--runtimeVersion <value>]
|
||||
[--appIdentifier <value>] [--buildProfile <value>] [--gitCommitHash <value>] [--limit <value>]
|
||||
|
||||
OPTIONS
|
||||
--appBuildVersion=appBuildVersion
|
||||
--appIdentifier=appIdentifier
|
||||
--appVersion=appVersion
|
||||
--buildProfile=buildProfile
|
||||
--channel=channel
|
||||
FLAGS
|
||||
--appBuildVersion=<value>
|
||||
--appIdentifier=<value>
|
||||
--appVersion=<value>
|
||||
--buildProfile=<value>
|
||||
--channel=<value>
|
||||
--distribution=(store|internal|simulator)
|
||||
--gitCommitHash=gitCommitHash
|
||||
|
||||
--gitCommitHash=<value>
|
||||
--json Enable JSON output, non-JSON messages will be printed
|
||||
to stderr
|
||||
|
||||
--limit=limit
|
||||
|
||||
--limit=<value>
|
||||
--platform=(all|android|ios)
|
||||
|
||||
--runtimeVersion=runtimeVersion
|
||||
|
||||
--sdkVersion=sdkVersion
|
||||
|
||||
--runtimeVersion=<value>
|
||||
--sdkVersion=<value>
|
||||
--status=(new|in-queue|in-progress|errored|finished|canceled)
|
||||
|
||||
DESCRIPTION
|
||||
list all builds for your project
|
||||
```
|
||||
|
||||
_See code: [src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/build/list.ts)_
|
||||
_See code: [src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/build/list.ts)_
|
||||
|
||||
## `eas build:view [BUILD_ID]`
|
||||
|
||||
@@ -245,13 +403,94 @@ view a build for your project
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas build:view [BUILD_ID]
|
||||
$ eas build:view [BUILD_ID] [--json]
|
||||
|
||||
OPTIONS
|
||||
FLAGS
|
||||
--json Enable JSON output, non-JSON messages will be printed to stderr
|
||||
|
||||
DESCRIPTION
|
||||
view a build for your project
|
||||
```
|
||||
|
||||
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/build/view.ts)_
|
||||
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/build/view.ts)_
|
||||
|
||||
## `eas channel:create [NAME]`
|
||||
|
||||
Create a channel on the current project.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas channel:create [NAME] [--json]
|
||||
|
||||
ARGUMENTS
|
||||
NAME Name of the channel to create
|
||||
|
||||
FLAGS
|
||||
--json print output as a JSON object with the new channel ID, name and branch mapping.
|
||||
|
||||
DESCRIPTION
|
||||
Create a channel on the current project.
|
||||
```
|
||||
|
||||
_See code: [src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/channel/create.ts)_
|
||||
|
||||
## `eas channel:edit [NAME]`
|
||||
|
||||
Point a channel at a new branch.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas channel:edit [NAME] [--branch <value>] [--json]
|
||||
|
||||
ARGUMENTS
|
||||
NAME Name of the channel to edit
|
||||
|
||||
FLAGS
|
||||
--branch=<value> Name of the branch to point to
|
||||
--json print output as a JSON object with the channel ID, name and branch mapping.
|
||||
|
||||
DESCRIPTION
|
||||
Point a channel at a new branch.
|
||||
```
|
||||
|
||||
_See code: [src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/channel/edit.ts)_
|
||||
|
||||
## `eas channel:list`
|
||||
|
||||
List all channels on the current project.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas channel:list [--json]
|
||||
|
||||
FLAGS
|
||||
--json print output as a JSON object with the channel ID, name and branch mapping.
|
||||
|
||||
DESCRIPTION
|
||||
List all channels on the current project.
|
||||
```
|
||||
|
||||
_See code: [src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/channel/list.ts)_
|
||||
|
||||
## `eas channel:view [NAME]`
|
||||
|
||||
View a channel on the current project.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas channel:view [NAME] [--json]
|
||||
|
||||
ARGUMENTS
|
||||
NAME Name of the channel to view
|
||||
|
||||
FLAGS
|
||||
--json print output as a JSON object with the channel ID, name and branch mapping.
|
||||
|
||||
DESCRIPTION
|
||||
View a channel on the current project.
|
||||
```
|
||||
|
||||
_See code: [src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/channel/view.ts)_
|
||||
|
||||
## `eas config`
|
||||
|
||||
@@ -259,14 +498,17 @@ show the eas.json config
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas config
|
||||
$ eas config [-p android|ios] [--profile <value>]
|
||||
|
||||
OPTIONS
|
||||
FLAGS
|
||||
-p, --platform=(android|ios)
|
||||
--profile=profile
|
||||
--profile=<value>
|
||||
|
||||
DESCRIPTION
|
||||
show the eas.json config
|
||||
```
|
||||
|
||||
_See code: [src/commands/config.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/config.ts)_
|
||||
_See code: [src/commands/config.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/config.ts)_
|
||||
|
||||
## `eas credentials`
|
||||
|
||||
@@ -275,9 +517,12 @@ manage your credentials
|
||||
```
|
||||
USAGE
|
||||
$ eas credentials
|
||||
|
||||
DESCRIPTION
|
||||
manage your credentials
|
||||
```
|
||||
|
||||
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/credentials.ts)_
|
||||
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/credentials.ts)_
|
||||
|
||||
## `eas device:create`
|
||||
|
||||
@@ -286,9 +531,12 @@ register new Apple Devices to use for internal distribution
|
||||
```
|
||||
USAGE
|
||||
$ eas device:create
|
||||
|
||||
DESCRIPTION
|
||||
register new Apple Devices to use for internal distribution
|
||||
```
|
||||
|
||||
_See code: [src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/device/create.ts)_
|
||||
_See code: [src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/device/create.ts)_
|
||||
|
||||
## `eas device:list`
|
||||
|
||||
@@ -296,13 +544,16 @@ list all registered devices for your account
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas device:list
|
||||
$ eas device:list [--apple-team-id <value>]
|
||||
|
||||
OPTIONS
|
||||
--apple-team-id=apple-team-id
|
||||
FLAGS
|
||||
--apple-team-id=<value>
|
||||
|
||||
DESCRIPTION
|
||||
list all registered devices for your account
|
||||
```
|
||||
|
||||
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/device/list.ts)_
|
||||
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/device/list.ts)_
|
||||
|
||||
## `eas device:view [UDID]`
|
||||
|
||||
@@ -311,9 +562,12 @@ view a device for your project
|
||||
```
|
||||
USAGE
|
||||
$ eas device:view [UDID]
|
||||
|
||||
DESCRIPTION
|
||||
view a device for your project
|
||||
```
|
||||
|
||||
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/device/view.ts)_
|
||||
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/device/view.ts)_
|
||||
|
||||
## `eas diagnostics`
|
||||
|
||||
@@ -322,26 +576,32 @@ log environment info to the console
|
||||
```
|
||||
USAGE
|
||||
$ eas diagnostics
|
||||
|
||||
DESCRIPTION
|
||||
log environment info to the console
|
||||
```
|
||||
|
||||
_See code: [src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/diagnostics.ts)_
|
||||
_See code: [src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/diagnostics.ts)_
|
||||
|
||||
## `eas help [COMMAND]`
|
||||
|
||||
display help for eas
|
||||
Display help for eas.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas help [COMMAND]
|
||||
$ eas help [COMMAND] [-n]
|
||||
|
||||
ARGUMENTS
|
||||
COMMAND command to show help for
|
||||
COMMAND Command to show help for.
|
||||
|
||||
OPTIONS
|
||||
--all see all commands in CLI
|
||||
FLAGS
|
||||
-n, --nested-commands Include all nested commands in the output.
|
||||
|
||||
DESCRIPTION
|
||||
Display help for eas.
|
||||
```
|
||||
|
||||
_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v3.2.5/src/commands/help.ts)_
|
||||
_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v5.1.10/src/commands/help.ts)_
|
||||
|
||||
## `eas project:info`
|
||||
|
||||
@@ -350,9 +610,12 @@ information about the current project
|
||||
```
|
||||
USAGE
|
||||
$ eas project:info
|
||||
|
||||
DESCRIPTION
|
||||
information about the current project
|
||||
```
|
||||
|
||||
_See code: [src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/project/info.ts)_
|
||||
_See code: [src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/project/info.ts)_
|
||||
|
||||
## `eas project:init`
|
||||
|
||||
@@ -362,11 +625,14 @@ create or link an EAS project
|
||||
USAGE
|
||||
$ eas project:init
|
||||
|
||||
DESCRIPTION
|
||||
create or link an EAS project
|
||||
|
||||
ALIASES
|
||||
$ eas init
|
||||
```
|
||||
|
||||
_See code: [src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/project/init.ts)_
|
||||
_See code: [src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/project/init.ts)_
|
||||
|
||||
## `eas secret:create`
|
||||
|
||||
@@ -374,16 +640,19 @@ Create an environment secret on the current project or owner account.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas secret:create
|
||||
$ eas secret:create [--scope account|project] [--name <value>] [--value <value>] [--force]
|
||||
|
||||
OPTIONS
|
||||
FLAGS
|
||||
--force Delete and recreate existing secrets
|
||||
--name=name Name of the secret
|
||||
--name=<value> Name of the secret
|
||||
--scope=(account|project) [default: project] Scope for the secret
|
||||
--value=value Value of the secret
|
||||
--value=<value> Value of the secret
|
||||
|
||||
DESCRIPTION
|
||||
Create an environment secret on the current project or owner account.
|
||||
```
|
||||
|
||||
_See code: [src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/secret/create.ts)_
|
||||
_See code: [src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/secret/create.ts)_
|
||||
|
||||
## `eas secret:delete`
|
||||
|
||||
@@ -391,16 +660,18 @@ Delete an environment secret by ID.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas secret:delete
|
||||
$ eas secret:delete [--id <value>]
|
||||
|
||||
OPTIONS
|
||||
--id=id ID of the secret to delete
|
||||
FLAGS
|
||||
--id=<value> ID of the secret to delete
|
||||
|
||||
DESCRIPTION
|
||||
Delete an environment secret by ID.
|
||||
|
||||
Unsure where to find the secret's ID? Run eas secret:list
|
||||
```
|
||||
|
||||
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/secret/delete.ts)_
|
||||
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/secret/delete.ts)_
|
||||
|
||||
## `eas secret:list`
|
||||
|
||||
@@ -409,9 +680,12 @@ Lists environment secrets available for your current app
|
||||
```
|
||||
USAGE
|
||||
$ eas secret:list
|
||||
|
||||
DESCRIPTION
|
||||
Lists environment secrets available for your current app
|
||||
```
|
||||
|
||||
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/secret/list.ts)_
|
||||
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/secret/list.ts)_
|
||||
|
||||
## `eas submit`
|
||||
|
||||
@@ -419,32 +693,130 @@ Submit build archive to App Store Connect
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas submit
|
||||
$ eas submit [-p android|ios|all] [--profile <value>] [--latest | --id <value> | --path <value> | --url
|
||||
<value>] [--verbose] [--wait] [--non-interactive]
|
||||
|
||||
OPTIONS
|
||||
FLAGS
|
||||
-p, --platform=(android|ios|all)
|
||||
--id=id ID of the build to submit
|
||||
--id=<value> ID of the build to submit
|
||||
--latest Submit the latest build for specified platform
|
||||
--non-interactive Run command in non-interactive mode
|
||||
--path=path Path to the .apk/.aab/.ipa file
|
||||
|
||||
--profile=profile Name of the submit profile from eas.json. Defaults to "production" if defined in
|
||||
--path=<value> Path to the .apk/.aab/.ipa file
|
||||
--profile=<value> Name of the submit profile from eas.json. Defaults to "production" if defined in
|
||||
eas.json.
|
||||
|
||||
--url=url App archive url
|
||||
|
||||
--url=<value> App archive url
|
||||
--verbose Always print logs from Submission Service
|
||||
|
||||
--[no-]wait Wait for submission to complete
|
||||
|
||||
DESCRIPTION
|
||||
Submit build archive to App Store Connect
|
||||
|
||||
See how to configure submits with eas.json: https://docs.expo.dev/submit/eas-json/
|
||||
|
||||
ALIASES
|
||||
$ eas build:submit
|
||||
```
|
||||
|
||||
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/submit.ts)_
|
||||
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/submit.ts)_
|
||||
|
||||
## `eas update`
|
||||
|
||||
Publish an update group.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas update [--branch <value>] [--message <value>] [--republish | --input-dir <value> | --skip-bundler]
|
||||
[--group <value> | | ] [-p android|ios|all] [--json] [--auto]
|
||||
|
||||
FLAGS
|
||||
-p, --platform=(android|ios|all) [default: all]
|
||||
--auto Use the current git branch and commit message for the EAS branch and update message
|
||||
--branch=<value> Branch to publish the update group on
|
||||
--group=<value> Update group to republish
|
||||
--input-dir=<value> [default: dist] Location of the bundle
|
||||
--json Enable JSON output, non-JSON messages will be printed to stderr
|
||||
--message=<value> A short message describing the update
|
||||
--republish Republish an update group
|
||||
--skip-bundler Skip running Expo CLI to bundle the app before publishing
|
||||
|
||||
DESCRIPTION
|
||||
Publish an update group.
|
||||
```
|
||||
|
||||
_See code: [src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/update/index.ts)_
|
||||
|
||||
## `eas update:configure`
|
||||
|
||||
Configure the project to support EAS Update.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas update:configure
|
||||
|
||||
DESCRIPTION
|
||||
Configure the project to support EAS Update.
|
||||
```
|
||||
|
||||
_See code: [src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/update/configure.ts)_
|
||||
|
||||
## `eas update:delete GROUPID`
|
||||
|
||||
Delete all the updates in an update Group.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas update:delete [GROUPID] [--json]
|
||||
|
||||
ARGUMENTS
|
||||
GROUPID The ID of an update group to delete.
|
||||
|
||||
FLAGS
|
||||
--json Return a json with the group ID of the deleted updates.
|
||||
|
||||
DESCRIPTION
|
||||
Delete all the updates in an update Group.
|
||||
```
|
||||
|
||||
_See code: [src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/update/delete.ts)_
|
||||
|
||||
## `eas update:list`
|
||||
|
||||
View the recent updates for a branch
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas update:list [--branch <value> | --all] [--json]
|
||||
|
||||
FLAGS
|
||||
--all List all updates associated with this project
|
||||
--branch=<value> List all updates on this branch
|
||||
--json Return a json with all of the recent update groups.
|
||||
|
||||
DESCRIPTION
|
||||
View the recent updates for a branch
|
||||
```
|
||||
|
||||
_See code: [src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/update/list.ts)_
|
||||
|
||||
## `eas update:view GROUPID`
|
||||
|
||||
Update group details.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas update:view [GROUPID] [--json]
|
||||
|
||||
ARGUMENTS
|
||||
GROUPID The ID of an update group.
|
||||
|
||||
FLAGS
|
||||
--json Return a json with the updates belonging to the group.
|
||||
|
||||
DESCRIPTION
|
||||
Update group details.
|
||||
```
|
||||
|
||||
_See code: [src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/update/view.ts)_
|
||||
|
||||
## `eas webhook:create`
|
||||
|
||||
@@ -452,18 +824,19 @@ Create a webhook on the current project.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas webhook:create
|
||||
$ eas webhook:create [--event BUILD|SUBMIT] [--url <value>] [--secret <value>]
|
||||
|
||||
OPTIONS
|
||||
FLAGS
|
||||
--event=(BUILD|SUBMIT) Event type that triggers the webhook
|
||||
|
||||
--secret=secret Secret used to create a hash signature of the request payload, provided in the
|
||||
--secret=<value> Secret used to create a hash signature of the request payload, provided in the
|
||||
'Expo-Signature' header.
|
||||
--url=<value> Webhook URL
|
||||
|
||||
--url=url Webhook URL
|
||||
DESCRIPTION
|
||||
Create a webhook on the current project.
|
||||
```
|
||||
|
||||
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/webhook/create.ts)_
|
||||
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/webhook/create.ts)_
|
||||
|
||||
## `eas webhook:delete [ID]`
|
||||
|
||||
@@ -475,9 +848,12 @@ USAGE
|
||||
|
||||
ARGUMENTS
|
||||
ID ID of the webhook to delete
|
||||
|
||||
DESCRIPTION
|
||||
Delete a webhook on the current project.
|
||||
```
|
||||
|
||||
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/webhook/delete.ts)_
|
||||
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/webhook/delete.ts)_
|
||||
|
||||
## `eas webhook:list`
|
||||
|
||||
@@ -485,13 +861,16 @@ List webhooks on the current project.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas webhook:list
|
||||
$ eas webhook:list [--event BUILD|SUBMIT]
|
||||
|
||||
OPTIONS
|
||||
FLAGS
|
||||
--event=(BUILD|SUBMIT) Event type that triggers the webhook
|
||||
|
||||
DESCRIPTION
|
||||
List webhooks on the current project.
|
||||
```
|
||||
|
||||
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/webhook/list.ts)_
|
||||
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/webhook/list.ts)_
|
||||
|
||||
## `eas webhook:update`
|
||||
|
||||
@@ -499,19 +878,20 @@ Create a webhook on the current project.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas webhook:update
|
||||
$ eas webhook:update --id <value> [--event BUILD|SUBMIT] [--url <value>] [--secret <value>]
|
||||
|
||||
OPTIONS
|
||||
FLAGS
|
||||
--event=(BUILD|SUBMIT) Event type that triggers the webhook
|
||||
--id=id (required) Webhook ID
|
||||
|
||||
--secret=secret Secret used to create a hash signature of the request payload, provided in the
|
||||
--id=<value> (required) Webhook ID
|
||||
--secret=<value> Secret used to create a hash signature of the request payload, provided in the
|
||||
'Expo-Signature' header.
|
||||
--url=<value> Webhook URL
|
||||
|
||||
--url=url Webhook URL
|
||||
DESCRIPTION
|
||||
Create a webhook on the current project.
|
||||
```
|
||||
|
||||
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/webhook/update.ts)_
|
||||
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/webhook/update.ts)_
|
||||
|
||||
## `eas webhook:view ID`
|
||||
|
||||
@@ -519,11 +899,14 @@ View a webhook on the current project.
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas webhook:view ID
|
||||
$ eas webhook:view [ID]
|
||||
|
||||
ARGUMENTS
|
||||
ID ID of the webhook to view
|
||||
|
||||
DESCRIPTION
|
||||
View a webhook on the current project.
|
||||
```
|
||||
|
||||
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v0.41.0/packages/eas-cli/src/commands/webhook/view.ts)_
|
||||
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v0.44.0/packages/eas-cli/src/commands/webhook/view.ts)_
|
||||
<!-- commandsstop -->
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const oclif = require('@oclif/core');
|
||||
const path = require('path');
|
||||
|
||||
const project = path.join(__dirname, '..', 'tsconfig.json');
|
||||
|
||||
// In dev mode -> use ts-node and dev plugins
|
||||
process.env.NODE_ENV = 'development';
|
||||
|
||||
require('ts-node').register({ project });
|
||||
|
||||
// In dev mode, always show stack traces
|
||||
oclif.settings.disableJsonFlag = true
|
||||
|
||||
// Start the CLI
|
||||
oclif.run().then(oclif.flush).catch(oclif.Errors.handle);
|
||||
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
|
||||
node "%~dp0\dev" %*
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
require('@oclif/command')
|
||||
require('@oclif/core')
|
||||
.run()
|
||||
.then(require('@oclif/command/flush'))
|
||||
.catch(require('@oclif/errors/handle'));
|
||||
.then(require('@oclif/core/flush'))
|
||||
.catch(require('@oclif/core/handle'));
|
||||
@@ -1,31 +1,30 @@
|
||||
{
|
||||
"name": "eas-cli",
|
||||
"description": "EAS command line tool",
|
||||
"version": "0.41.0",
|
||||
"version": "0.44.0",
|
||||
"author": "Expo <[email protected]>",
|
||||
"bin": {
|
||||
"eas": "./bin/run"
|
||||
},
|
||||
"bugs": "https://github.com/expo/eas-cli/issues",
|
||||
"dependencies": {
|
||||
"@expo/apple-utils": "0.0.0-alpha.26",
|
||||
"@expo/apple-utils": "0.0.0-alpha.27",
|
||||
"@expo/config": "6.0.11",
|
||||
"@expo/config-plugins": "4.0.11",
|
||||
"@expo/eas-build-job": "0.2.61",
|
||||
"@expo/eas-json": "^0.41.0",
|
||||
"@expo/eas-json": "0.44.0",
|
||||
"@expo/json-file": "8.2.34",
|
||||
"@expo/pkcs12": "0.0.6",
|
||||
"@expo/plist": "0.0.16",
|
||||
"@expo/plugin-warn-if-update-available": "1.7.1",
|
||||
"@expo/plugin-autocomplete": "1.0.2",
|
||||
"@expo/plugin-warn-if-update-available": "2.0.1",
|
||||
"@expo/prebuild-config": "3.0.11",
|
||||
"@expo/results": "1.0.0",
|
||||
"@expo/rudder-sdk-node": "1.1.1",
|
||||
"@expo/spawn-async": "1.5.0",
|
||||
"@expo/timeago.js": "1.0.0",
|
||||
"@oclif/command": "1.8.3",
|
||||
"@oclif/config": "1.17.1",
|
||||
"@oclif/errors": "1.3.5",
|
||||
"@oclif/plugin-help": "3.2.5",
|
||||
"@oclif/core": "1.0.10",
|
||||
"@oclif/plugin-help": "5.1.10",
|
||||
"@urql/core": "2.3.1",
|
||||
"@urql/exchange-retry": "0.3.0",
|
||||
"chalk": "4.1.2",
|
||||
@@ -118,7 +117,8 @@
|
||||
"commands": "./build/commands",
|
||||
"plugins": [
|
||||
"@oclif/plugin-help",
|
||||
"@expo/plugin-warn-if-update-available"
|
||||
"@expo/plugin-warn-if-update-available",
|
||||
"@expo/plugin-autocomplete"
|
||||
],
|
||||
"topics": {
|
||||
"account": {
|
||||
@@ -165,18 +165,25 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalHelpFlags": [
|
||||
"-h"
|
||||
],
|
||||
"additionalVersionFlags": [
|
||||
"-v"
|
||||
]
|
||||
},
|
||||
"repository": "expo/eas-cli",
|
||||
"scripts": {
|
||||
"postpack": "rm -f oclif.manifest.json",
|
||||
"prepack": "rm -rf build && yarn build && yarn oclif-dev manifest && yarn oclif-dev readme && node patch-readme",
|
||||
"prepack": "./scripts/prepack.sh",
|
||||
"pretarball-ci": "./scripts/pretarball-ci.sh",
|
||||
"build": "tsc --project tsconfig.build.json",
|
||||
"watch": "yarn build --watch --preserveWatchOutput",
|
||||
"typecheck": "tsc",
|
||||
"test": "jest",
|
||||
"version": "yarn oclif-dev readme && node patch-readme && git add README.md",
|
||||
"version": "yarn oclif readme && node scripts/patch-readme && git add README.md",
|
||||
"generate-graphql-code": "graphql-codegen --config graphql-codegen.yml",
|
||||
"clean": "rm -rf dist build node_modules yarn-error.log"
|
||||
"clean": "rm -rf dist build tmp node_modules yarn-error.log"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
const { promises: fs } = require('fs');
|
||||
|
||||
(async () => {
|
||||
// Patch `oclif-dev readme` path and link generation
|
||||
// Patch `oclif readme` path and link generation
|
||||
let readmeContent = await fs.readFile('README.md', 'utf8');
|
||||
readmeContent = readmeContent.replace(/\[build\//g, '[src/');
|
||||
readmeContent = readmeContent.replace(/build\/commands/g, 'packages/eas-cli/src/commands');
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
rm -rf build
|
||||
yarn build
|
||||
|
||||
if [ -z "$CLI_SIZE_CHECK" ]; then
|
||||
yarn oclif manifest
|
||||
fi
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
EAS_CLI_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/.. && pwd )"
|
||||
PACKAGE_JSON_PATH="$EAS_CLI_DIR/package.json"
|
||||
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
sed -i '' "s/\\\"@expo\/eas-json\\\": \\\".*\\\"/\\\"@expo\/eas-json\\\": \\\"file:..\/..\/..\/eas-json\\\"/g" $PACKAGE_JSON_PATH
|
||||
else
|
||||
sed -i "s/\\\"@expo\/eas-json\\\": \\\".*\\\"/\\\"@expo\/eas-json\\\": \\\"file:..\/..\/..\/eas-json\\\"/g" $PACKAGE_JSON_PATH
|
||||
fi
|
||||
@@ -57,3 +57,13 @@ export function getExpoWebsiteBaseUrl(): string {
|
||||
return `https://expo.dev`;
|
||||
}
|
||||
}
|
||||
|
||||
export function getEASUpdateURL(projectId: string): string {
|
||||
if (process.env.EXPO_STAGING) {
|
||||
return new URL(projectId, `https://staging-u.expo.dev`).href;
|
||||
} else if (process.env.EXPO_LOCAL) {
|
||||
return new URL(`expo-updates/${projectId}`, `http://127.0.0.1:3000`).href;
|
||||
} else {
|
||||
return new URL(projectId, `https://u.expo.dev`).href;
|
||||
}
|
||||
}
|
||||
@@ -1,63 +1,29 @@
|
||||
import { ExpoConfig } from '@expo/config';
|
||||
import { AndroidConfig, AndroidManifest } from '@expo/config-plugins';
|
||||
|
||||
import Log from '../../log';
|
||||
import { getProjectAccountName } from '../../project/projectUtils';
|
||||
import { ensureLoggedInAsync } from '../../user/actions';
|
||||
import { ensureValidVersions } from '../utils/updates';
|
||||
|
||||
export async function configureUpdatesAsync(projectDir: string, exp: ExpoConfig): Promise<void> {
|
||||
ensureValidVersions(exp);
|
||||
const accountName = getProjectAccountName(exp, await ensureLoggedInAsync());
|
||||
|
||||
const androidManifestPath = await AndroidConfig.Paths.getAndroidManifestAsync(projectDir);
|
||||
const androidManifest = await getAndroidManifestAsync(projectDir);
|
||||
|
||||
if (!AndroidConfig.Updates.isMainApplicationMetaDataSynced(exp, androidManifest, accountName)) {
|
||||
const result = AndroidConfig.Updates.setUpdatesConfig(exp, androidManifest, accountName);
|
||||
|
||||
await AndroidConfig.Manifest.writeAndroidManifestAsync(androidManifestPath, result);
|
||||
}
|
||||
}
|
||||
|
||||
export async function syncUpdatesConfigurationAsync(
|
||||
projectDir: string,
|
||||
exp: ExpoConfig
|
||||
): Promise<void> {
|
||||
ensureValidVersions(exp);
|
||||
const accountName = getProjectAccountName(exp, await ensureLoggedInAsync());
|
||||
try {
|
||||
await ensureUpdatesConfiguredAsync(projectDir);
|
||||
} catch (error) {
|
||||
Log.error(
|
||||
'expo-updates module is not configured. Please run "eas build:configure" first to configure the project'
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const androidManifestPath = await AndroidConfig.Paths.getAndroidManifestAsync(projectDir);
|
||||
let androidManifest = await getAndroidManifestAsync(projectDir);
|
||||
|
||||
if (!AndroidConfig.Updates.areVersionsSynced(exp, androidManifest)) {
|
||||
androidManifest = AndroidConfig.Updates.setVersionsConfig(exp, androidManifest);
|
||||
await AndroidConfig.Manifest.writeAndroidManifestAsync(androidManifestPath, androidManifest);
|
||||
}
|
||||
|
||||
if (!AndroidConfig.Updates.isMainApplicationMetaDataSynced(exp, androidManifest, accountName)) {
|
||||
Log.warn(
|
||||
'Native project configuration is not synced with values present in your app.json, run "eas build:configure" to make sure all values are applied in the native project'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Note: we assume here that Expo modules are properly configured in the project. Aside from that,
|
||||
// all that is needed on Expo SDK 43+ to configure expo-updates configuration in AndroidManifest.xml
|
||||
async function ensureUpdatesConfiguredAsync(projectDir: string): Promise<void> {
|
||||
const androidManifest = await getAndroidManifestAsync(projectDir);
|
||||
|
||||
if (!AndroidConfig.Updates.isMainApplicationMetaDataSet(androidManifest)) {
|
||||
throw new Error('Missing values in AndroidManifest.xml');
|
||||
}
|
||||
const updatedAndroidManifest = AndroidConfig.Updates.setUpdatesConfig(
|
||||
exp,
|
||||
androidManifest,
|
||||
accountName
|
||||
);
|
||||
await AndroidConfig.Manifest.writeAndroidManifestAsync(
|
||||
androidManifestPath,
|
||||
updatedAndroidManifest
|
||||
);
|
||||
}
|
||||
|
||||
export async function readReleaseChannelSafelyAsync(projectDir: string): Promise<string | null> {
|
||||
|
||||
@@ -24,9 +24,9 @@ import { AndroidBuildContext, BuildContext, CommonContext } from '../context';
|
||||
import { transformMetadata } from '../graphql';
|
||||
import { logCredentialsSource } from '../utils/credentials';
|
||||
import { checkGoogleServicesFileAsync, checkNodeEnvVariable } from '../validate';
|
||||
import { validateAndSyncProjectConfigurationAsync } from './configure';
|
||||
import { transformJob } from './graphql';
|
||||
import { prepareJobAsync } from './prepareJob';
|
||||
import { syncProjectConfigurationAsync } from './syncProjectConfiguration';
|
||||
|
||||
export async function createAndroidContextAsync(
|
||||
ctx: CommonContext<Platform.ANDROID>
|
||||
@@ -71,8 +71,8 @@ export async function prepareAndroidBuildAsync(
|
||||
ensureCredentialsAsync: async (ctx: BuildContext<Platform.ANDROID>) => {
|
||||
return await ensureAndroidCredentialsAsync(ctx);
|
||||
},
|
||||
ensureProjectConfiguredAsync: async () => {
|
||||
await validateAndSyncProjectConfigurationAsync({
|
||||
syncProjectConfigurationAsync: async () => {
|
||||
await syncProjectConfigurationAsync({
|
||||
projectDir: ctx.projectDir,
|
||||
exp: ctx.exp,
|
||||
buildProfile: ctx.buildProfile,
|
||||
|
||||
+25
-32
@@ -2,39 +2,17 @@ import { ExpoConfig } from '@expo/config';
|
||||
import { AndroidConfig } from '@expo/config-plugins';
|
||||
import { Platform, Workflow } from '@expo/eas-build-job';
|
||||
import { AndroidVersionAutoIncrement, BuildProfile } from '@expo/eas-json';
|
||||
import chalk from 'chalk';
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
|
||||
import Log from '../../log';
|
||||
import {
|
||||
ensureApplicationIdIsDefinedForManagedProjectAsync,
|
||||
warnIfAndroidPackageDefinedInAppConfigForBareWorkflowProject,
|
||||
} from '../../project/android/applicationId';
|
||||
import { resolveWorkflowAsync } from '../../project/workflow';
|
||||
import { getVcsClient } from '../../vcs';
|
||||
import { ConfigureContext } from '../context';
|
||||
import { isExpoUpdatesInstalled } from '../utils/updates';
|
||||
import { configureUpdatesAsync, syncUpdatesConfigurationAsync } from './UpdatesModule';
|
||||
import { syncUpdatesConfigurationAsync } from './UpdatesModule';
|
||||
import { BumpStrategy, bumpVersionAsync, bumpVersionInAppJsonAsync } from './version';
|
||||
|
||||
export async function configureAndroidAsync(ctx: ConfigureContext): Promise<void> {
|
||||
if (!ctx.hasAndroidNativeProject) {
|
||||
await ensureApplicationIdIsDefinedForManagedProjectAsync(ctx.projectDir, ctx.exp);
|
||||
return;
|
||||
}
|
||||
|
||||
warnIfAndroidPackageDefinedInAppConfigForBareWorkflowProject(ctx.projectDir, ctx.exp);
|
||||
|
||||
await AndroidConfig.EasBuild.configureEasBuildAsync(ctx.projectDir);
|
||||
|
||||
const easGradlePath = AndroidConfig.EasBuild.getEasBuildGradlePath(ctx.projectDir);
|
||||
await getVcsClient().trackFileAsync(easGradlePath);
|
||||
|
||||
if (isExpoUpdatesInstalled(ctx.projectDir)) {
|
||||
await configureUpdatesAsync(ctx.projectDir, ctx.exp);
|
||||
}
|
||||
Log.withTick('Android project configured');
|
||||
}
|
||||
|
||||
export async function validateAndSyncProjectConfigurationAsync({
|
||||
export async function syncProjectConfigurationAsync({
|
||||
projectDir,
|
||||
exp,
|
||||
buildProfile,
|
||||
@@ -48,11 +26,7 @@ export async function validateAndSyncProjectConfigurationAsync({
|
||||
const versionBumpStrategy = resolveVersionBumpStrategy(autoIncrement ?? false);
|
||||
|
||||
if (workflow === Workflow.GENERIC) {
|
||||
if (!(await AndroidConfig.EasBuild.isEasBuildGradleConfiguredAsync(projectDir))) {
|
||||
throw new Error(
|
||||
'Project is not configured. Please run "eas build:configure" to configure the project.'
|
||||
);
|
||||
}
|
||||
await cleanUpOldEasBuildGradleScriptAsync(projectDir);
|
||||
if (isExpoUpdatesInstalled(projectDir)) {
|
||||
await syncUpdatesConfigurationAsync(projectDir, exp);
|
||||
}
|
||||
@@ -73,3 +47,22 @@ function resolveVersionBumpStrategy(autoIncrement: AndroidVersionAutoIncrement):
|
||||
return BumpStrategy.APP_VERSION;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove this after a few months
|
||||
export async function cleanUpOldEasBuildGradleScriptAsync(projectDir: string): Promise<void> {
|
||||
const easBuildGradlePath = path.join(projectDir, 'android', 'app', 'eas-build.gradle');
|
||||
if (await fs.pathExists(easBuildGradlePath)) {
|
||||
Log.withTick(`Removing ${chalk.bold('eas-build.gradle')} as it's not longer necessary`);
|
||||
await fs.remove(easBuildGradlePath);
|
||||
|
||||
const buildGradlePath = AndroidConfig.Paths.getAppBuildGradleFilePath(projectDir);
|
||||
const buildGradleContents = await fs.readFile(buildGradlePath, 'utf-8');
|
||||
const buildGradleContentsWithoutApply = buildGradleContents.replace(
|
||||
/apply from: ["'].\/eas-build.gradle["']\n/,
|
||||
''
|
||||
);
|
||||
if (buildGradleContentsWithoutApply !== buildGradleContents) {
|
||||
await fs.writeFile(buildGradlePath, buildGradleContentsWithoutApply);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ interface Builder<TPlatform extends Platform, Credentials, TJob extends Job> {
|
||||
ensureCredentialsAsync(
|
||||
ctx: BuildContext<TPlatform>
|
||||
): Promise<CredentialsResult<Credentials> | undefined>;
|
||||
ensureProjectConfiguredAsync(ctx: BuildContext<TPlatform>): Promise<void>;
|
||||
syncProjectConfigurationAsync(ctx: BuildContext<TPlatform>): Promise<void>;
|
||||
prepareJobAsync(ctx: BuildContext<TPlatform>, jobData: JobData<Credentials>): Promise<Job>;
|
||||
sendBuildRequestAsync(appId: string, job: TJob, metadata: Metadata): Promise<BuildResult>;
|
||||
}
|
||||
@@ -60,14 +60,13 @@ export async function prepareBuildRequestForPlatformAsync<
|
||||
trackingCtx: ctx.trackingCtx,
|
||||
}
|
||||
);
|
||||
if (!ctx.skipProjectConfiguration) {
|
||||
await withAnalyticsAsync(async () => await builder.ensureProjectConfiguredAsync(ctx), {
|
||||
attemptEvent: BuildEvent.CONFIGURE_PROJECT_ATTEMPT,
|
||||
successEvent: BuildEvent.CONFIGURE_PROJECT_SUCCESS,
|
||||
failureEvent: BuildEvent.CONFIGURE_PROJECT_FAIL,
|
||||
trackingCtx: ctx.trackingCtx,
|
||||
});
|
||||
}
|
||||
|
||||
await withAnalyticsAsync(async () => await builder.syncProjectConfigurationAsync(ctx), {
|
||||
attemptEvent: BuildEvent.CONFIGURE_PROJECT_ATTEMPT,
|
||||
successEvent: BuildEvent.CONFIGURE_PROJECT_SUCCESS,
|
||||
failureEvent: BuildEvent.CONFIGURE_PROJECT_FAIL,
|
||||
trackingCtx: ctx.trackingCtx,
|
||||
});
|
||||
|
||||
if (await getVcsClient().isCommitRequiredAsync()) {
|
||||
Log.addNewLineIfNone();
|
||||
|
||||
@@ -1,97 +1,47 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { Platform, Workflow } from '@expo/eas-build-job';
|
||||
import { EasJson, EasJsonReader } from '@expo/eas-json';
|
||||
import { error } from '@oclif/errors';
|
||||
import chalk from 'chalk';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
import Log, { learnMore } from '../log';
|
||||
import { RequestedPlatform } from '../platform';
|
||||
import Log from '../log';
|
||||
import { resolveWorkflowAsync } from '../project/workflow';
|
||||
import { confirmAsync, promptAsync } from '../prompts';
|
||||
import { ensureLoggedInAsync } from '../user/actions';
|
||||
import { easCliVersion } from '../utils/easCli';
|
||||
import { getVcsClient } from '../vcs';
|
||||
import { configureAndroidAsync } from './android/configure';
|
||||
import { ConfigureContext } from './context';
|
||||
import { configureIosAsync } from './ios/configure';
|
||||
import { commitPromptAsync, maybeBailOnRepoStatusAsync } from './utils/repository';
|
||||
import { maybeBailOnRepoStatusAsync, reviewAndCommitChangesAsync } from './utils/repository';
|
||||
|
||||
const configureCommitMessage = {
|
||||
[RequestedPlatform.Android]: 'Configure EAS Build for Android',
|
||||
[RequestedPlatform.Ios]: 'Configure EAS Build for iOS',
|
||||
[RequestedPlatform.All]: 'Configure EAS Build',
|
||||
};
|
||||
|
||||
export async function ensureProjectConfiguredAsync(
|
||||
projectDir: string,
|
||||
requestedPlatform: RequestedPlatform
|
||||
): Promise<void> {
|
||||
if (await fs.pathExists(EasJsonReader.formatEasJsonPath(projectDir))) {
|
||||
return;
|
||||
}
|
||||
|
||||
const message = 'This project is not configured to build with EAS. Set it up now?';
|
||||
const confirm = await confirmAsync({ message });
|
||||
if (confirm) {
|
||||
await configureAsync({
|
||||
projectDir,
|
||||
platform: requestedPlatform,
|
||||
});
|
||||
if (await getVcsClient().isCommitRequiredAsync()) {
|
||||
error(
|
||||
'Build process requires clean working tree, please commit all your changes and run `eas build` again',
|
||||
{ exit: 1 }
|
||||
);
|
||||
}
|
||||
} else {
|
||||
error(
|
||||
`Aborting, please run ${chalk.bold('eas build:configure')} or create eas.json (${learnMore(
|
||||
'https://docs.expo.dev/build/eas-json'
|
||||
)})`,
|
||||
{ exit: 1 }
|
||||
);
|
||||
}
|
||||
interface ConfigureParams {
|
||||
projectDir: string;
|
||||
nonInteractive: boolean;
|
||||
}
|
||||
|
||||
export async function configureAsync(options: {
|
||||
platform: RequestedPlatform;
|
||||
projectDir: string;
|
||||
}): Promise<void> {
|
||||
/**
|
||||
* Creates eas.json if it does not exist.
|
||||
*
|
||||
* Returns:
|
||||
* - false - if eas.json already exists
|
||||
* - true - if eas.json was created by the function
|
||||
*/
|
||||
export async function ensureProjectConfiguredAsync(
|
||||
configureParams: ConfigureParams
|
||||
): Promise<boolean> {
|
||||
if (await fs.pathExists(EasJsonReader.formatEasJsonPath(configureParams.projectDir))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await configureAsync(configureParams);
|
||||
return true;
|
||||
}
|
||||
|
||||
async function configureAsync({ projectDir, nonInteractive }: ConfigureParams): Promise<void> {
|
||||
await maybeBailOnRepoStatusAsync();
|
||||
|
||||
const { exp } = getConfig(options.projectDir, { skipSDKVersionRequirement: true });
|
||||
|
||||
const ctx: ConfigureContext = {
|
||||
user: await ensureLoggedInAsync(),
|
||||
projectDir: options.projectDir,
|
||||
exp,
|
||||
requestedPlatform: options.platform,
|
||||
shouldConfigureAndroid: [RequestedPlatform.All, RequestedPlatform.Android].includes(
|
||||
options.platform
|
||||
),
|
||||
shouldConfigureIos: [RequestedPlatform.All, RequestedPlatform.Ios].includes(options.platform),
|
||||
hasAndroidNativeProject:
|
||||
(await resolveWorkflowAsync(options.projectDir, Platform.ANDROID)) === Workflow.GENERIC,
|
||||
hasIosNativeProject:
|
||||
(await resolveWorkflowAsync(options.projectDir, Platform.IOS)) === Workflow.GENERIC,
|
||||
};
|
||||
|
||||
Log.newLine();
|
||||
await ensureEasJsonExistsAsync(ctx);
|
||||
if (ctx.shouldConfigureAndroid) {
|
||||
await configureAndroidAsync(ctx);
|
||||
}
|
||||
if (ctx.shouldConfigureIos) {
|
||||
await configureIosAsync(ctx);
|
||||
}
|
||||
await createEasJsonAsync(projectDir);
|
||||
|
||||
if (await getVcsClient().isCommitRequiredAsync()) {
|
||||
Log.newLine();
|
||||
await reviewAndCommitChangesAsync(configureCommitMessage[options.platform]);
|
||||
} else if (!(await getVcsClient().hasUncommittedChangesAsync())) {
|
||||
Log.newLine();
|
||||
Log.withTick('No changes were necessary, the project is already configured correctly.');
|
||||
await reviewAndCommitChangesAsync('Configure EAS Build', {
|
||||
nonInteractive,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,58 +88,19 @@ const EAS_JSON_BARE_DEFAULT: EasJson = {
|
||||
},
|
||||
};
|
||||
|
||||
export async function ensureEasJsonExistsAsync(ctx: ConfigureContext): Promise<void> {
|
||||
const easJsonPath = EasJsonReader.formatEasJsonPath(ctx.projectDir);
|
||||
|
||||
if (await fs.pathExists(easJsonPath)) {
|
||||
const reader = new EasJsonReader(ctx.projectDir);
|
||||
await reader.readAsync();
|
||||
|
||||
Log.withTick('Validated eas.json');
|
||||
return;
|
||||
}
|
||||
async function createEasJsonAsync(projectDir: string): Promise<void> {
|
||||
const easJsonPath = EasJsonReader.formatEasJsonPath(projectDir);
|
||||
|
||||
const hasAndroidNativeProject =
|
||||
(await resolveWorkflowAsync(projectDir, Platform.ANDROID)) === Workflow.GENERIC;
|
||||
const hasIosNativeProject =
|
||||
(await resolveWorkflowAsync(projectDir, Platform.IOS)) === Workflow.GENERIC;
|
||||
const easJson =
|
||||
ctx.hasAndroidNativeProject && ctx.hasIosNativeProject
|
||||
hasAndroidNativeProject || hasIosNativeProject
|
||||
? EAS_JSON_BARE_DEFAULT
|
||||
: EAS_JSON_MANAGED_DEFAULT;
|
||||
|
||||
await fs.writeFile(easJsonPath, `${JSON.stringify(easJson, null, 2)}\n`);
|
||||
await getVcsClient().trackFileAsync(easJsonPath);
|
||||
Log.withTick('Generated eas.json');
|
||||
}
|
||||
|
||||
enum ShouldCommitChanges {
|
||||
Yes,
|
||||
ShowDiffFirst,
|
||||
Skip,
|
||||
}
|
||||
|
||||
async function reviewAndCommitChangesAsync(
|
||||
initialCommitMessage: string,
|
||||
askedFirstTime: boolean = true
|
||||
): Promise<void> {
|
||||
const { selected } = await promptAsync({
|
||||
type: 'select',
|
||||
name: 'selected',
|
||||
message: 'Can we commit these changes to git for you?',
|
||||
choices: [
|
||||
{ title: 'Yes', value: ShouldCommitChanges.Yes },
|
||||
...(askedFirstTime
|
||||
? [{ title: 'Show the diff and ask me again', value: ShouldCommitChanges.ShowDiffFirst }]
|
||||
: []),
|
||||
{
|
||||
title: 'Skip committing changes, I will do it later on my own',
|
||||
value: ShouldCommitChanges.Skip,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
if (selected === ShouldCommitChanges.Yes) {
|
||||
await commitPromptAsync({ initialCommitMessage });
|
||||
Log.withTick('Committed changes');
|
||||
} else if (selected === ShouldCommitChanges.ShowDiffFirst) {
|
||||
await getVcsClient().showDiffAsync();
|
||||
await reviewAndCommitChangesAsync(initialCommitMessage, false);
|
||||
}
|
||||
Log.withTick(`Generated ${chalk.bold('eas.json')}`);
|
||||
}
|
||||
@@ -6,23 +6,11 @@ import type { XCBuildConfiguration } from 'xcode';
|
||||
import { TrackingContext } from '../analytics/common';
|
||||
import { CredentialsContext } from '../credentials/context';
|
||||
import { Target } from '../credentials/ios/types';
|
||||
import { RequestedPlatform } from '../platform';
|
||||
import { GradleBuildContext } from '../project/android/gradle';
|
||||
import { XcodeBuildContext } from '../project/ios/scheme';
|
||||
import { Actor } from '../user/User';
|
||||
import { LocalBuildOptions } from './local';
|
||||
|
||||
export interface ConfigureContext {
|
||||
user: Actor;
|
||||
projectDir: string;
|
||||
exp: ExpoConfig;
|
||||
requestedPlatform: RequestedPlatform;
|
||||
shouldConfigureAndroid: boolean;
|
||||
shouldConfigureIos: boolean;
|
||||
hasAndroidNativeProject: boolean;
|
||||
hasIosNativeProject: boolean;
|
||||
}
|
||||
|
||||
export type CommonContext<T extends Platform> = Omit<BuildContext<T>, 'android' | 'ios'>;
|
||||
|
||||
export interface AndroidBuildContext {
|
||||
@@ -51,7 +39,6 @@ export interface BuildContext<T extends Platform> {
|
||||
projectDir: string;
|
||||
projectId: string;
|
||||
projectName: string;
|
||||
skipProjectConfiguration: boolean;
|
||||
trackingCtx: TrackingContext;
|
||||
user: Actor;
|
||||
workflow: Workflow;
|
||||
|
||||
@@ -25,7 +25,6 @@ export async function createBuildContextAsync<T extends Platform>({
|
||||
nonInteractive = false,
|
||||
platform,
|
||||
projectDir,
|
||||
skipProjectConfiguration = false,
|
||||
}: {
|
||||
buildProfileName: string;
|
||||
buildProfile: BuildProfile<T>;
|
||||
@@ -34,7 +33,6 @@ export async function createBuildContextAsync<T extends Platform>({
|
||||
nonInteractive: boolean;
|
||||
platform: T;
|
||||
projectDir: string;
|
||||
skipProjectConfiguration: boolean;
|
||||
}): Promise<BuildContext<T>> {
|
||||
const exp = getExpoConfig(projectDir, { env: buildProfile.env });
|
||||
|
||||
@@ -81,7 +79,6 @@ export async function createBuildContextAsync<T extends Platform>({
|
||||
projectDir,
|
||||
projectId,
|
||||
projectName,
|
||||
skipProjectConfiguration,
|
||||
trackingCtx,
|
||||
user,
|
||||
workflow,
|
||||
|
||||
@@ -1,60 +1,21 @@
|
||||
import { ExpoConfig } from '@expo/config';
|
||||
import { IOSConfig } from '@expo/config-plugins';
|
||||
|
||||
import Log from '../../log';
|
||||
import { getProjectAccountName } from '../../project/projectUtils';
|
||||
import { ensureLoggedInAsync } from '../../user/actions';
|
||||
import { readPlistAsync, writePlistAsync } from '../../utils/plist';
|
||||
import { getVcsClient } from '../../vcs';
|
||||
import { ensureValidVersions } from '../utils/updates';
|
||||
|
||||
export async function configureUpdatesAsync(projectDir: string, exp: ExpoConfig): Promise<void> {
|
||||
ensureValidVersions(exp);
|
||||
const accountName = getProjectAccountName(exp, await ensureLoggedInAsync());
|
||||
|
||||
let expoPlist = await readExpoPlistAsync(projectDir);
|
||||
if (!IOSConfig.Updates.isPlistConfigurationSynced(exp, expoPlist, accountName)) {
|
||||
expoPlist = IOSConfig.Updates.setUpdatesConfig(exp, expoPlist, accountName);
|
||||
await writeExpoPlistAsync(projectDir, expoPlist);
|
||||
}
|
||||
// TODO: ensure ExpoPlist in pbxproj
|
||||
}
|
||||
|
||||
export async function syncUpdatesConfigurationAsync(
|
||||
projectDir: string,
|
||||
exp: ExpoConfig
|
||||
): Promise<void> {
|
||||
ensureValidVersions(exp);
|
||||
const accountName = getProjectAccountName(exp, await ensureLoggedInAsync());
|
||||
try {
|
||||
await ensureUpdatesConfiguredAsync(projectDir);
|
||||
} catch (error) {
|
||||
Log.error(
|
||||
'expo-updates module is not configured. Please run "eas build:configure" first to configure the project'
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
|
||||
let expoPlist = await readExpoPlistAsync(projectDir);
|
||||
if (!IOSConfig.Updates.isPlistVersionConfigurationSynced(exp, expoPlist)) {
|
||||
expoPlist = IOSConfig.Updates.setVersionsConfig(exp, expoPlist);
|
||||
await writeExpoPlistAsync(projectDir, expoPlist);
|
||||
}
|
||||
|
||||
if (!IOSConfig.Updates.isPlistConfigurationSynced(exp, expoPlist, accountName)) {
|
||||
Log.warn(
|
||||
'Native project configuration is not synced with values present in your app.json, run "eas build:configure" to make sure all values are applied in the native project'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Note: we assume here that Expo modules are properly configured in the project. Aside from that,
|
||||
// all that is needed on Expo SDK 43+ to configure expo-updates configuration in Expo.plist
|
||||
async function ensureUpdatesConfiguredAsync(projectDir: string): Promise<void> {
|
||||
const expoPlist = await readExpoPlistAsync(projectDir);
|
||||
if (!IOSConfig.Updates.isPlistConfigurationSet(expoPlist)) {
|
||||
throw new Error('Missing values in Expo.plist');
|
||||
}
|
||||
const updatedExpoPlist = IOSConfig.Updates.setUpdatesConfig(exp, expoPlist, accountName);
|
||||
await writeExpoPlistAsync(projectDir, updatedExpoPlist);
|
||||
}
|
||||
|
||||
async function readExpoPlistAsync(projectDir: string): Promise<IOSConfig.ExpoPlist> {
|
||||
@@ -82,8 +43,10 @@ export async function readReleaseChannelSafelyAsync(projectDir: string): Promise
|
||||
|
||||
export async function readChannelSafelyAsync(projectDir: string): Promise<string | null> {
|
||||
try {
|
||||
const expoPlist: any = await readExpoPlistAsync(projectDir); // TODO-JJ remove any once IOSConfig.ExpoPlist is updated to include `EXUpdatesRequestHeaders : Record<string,string>`
|
||||
const updatesRequestHeaders = expoPlist['EXUpdatesRequestHeaders'] ?? {}; //TODO-JJ 'EXUpdatesRequestHeaders' IosConfig.Updates.Config.UPDATES_CONFIGURATION_REQUEST_HEADERS_KEY once https://github.com/expo/expo-cli/pull/3571 is published
|
||||
// TODO-JJ remove any once IOSConfig.ExpoPlist is updated to include `EXUpdatesRequestHeaders : Record<string,string>`
|
||||
const expoPlist: any = await readExpoPlistAsync(projectDir);
|
||||
//TODO-JJ 'EXUpdatesRequestHeaders' IosConfig.Updates.Config.UPDATES_CONFIGURATION_REQUEST_HEADERS_KEY once https://github.com/expo/expo-cli/pull/3571 is published
|
||||
const updatesRequestHeaders = expoPlist['EXUpdatesRequestHeaders'] ?? {};
|
||||
return updatesRequestHeaders['expo-channel-name'] ?? null;
|
||||
} catch (err) {
|
||||
return null;
|
||||
|
||||
@@ -11,10 +11,10 @@ import { BuildRequestSender, JobData, prepareBuildRequestForPlatformAsync } from
|
||||
import { BuildContext, CommonContext, IosBuildContext } from '../context';
|
||||
import { transformMetadata } from '../graphql';
|
||||
import { checkGoogleServicesFileAsync, checkNodeEnvVariable } from '../validate';
|
||||
import { validateAndSyncProjectConfigurationAsync } from './configure';
|
||||
import { ensureIosCredentialsAsync } from './credentials';
|
||||
import { transformJob } from './graphql';
|
||||
import { prepareJobAsync } from './prepareJob';
|
||||
import { syncProjectConfigurationAsync } from './syncProjectConfiguration';
|
||||
|
||||
export async function createIosContextAsync(
|
||||
ctx: CommonContext<Platform.IOS>
|
||||
@@ -63,8 +63,8 @@ export async function prepareIosBuildAsync(
|
||||
ensureCredentialsAsync: async (ctx: BuildContext<Platform.IOS>) => {
|
||||
return ensureIosCredentialsAsync(ctx, ctx.ios.targets);
|
||||
},
|
||||
ensureProjectConfiguredAsync: async () => {
|
||||
await validateAndSyncProjectConfigurationAsync({
|
||||
syncProjectConfigurationAsync: async () => {
|
||||
await syncProjectConfigurationAsync({
|
||||
projectDir: ctx.projectDir,
|
||||
exp: ctx.exp,
|
||||
buildProfile: ctx.buildProfile,
|
||||
|
||||
+2
-22
@@ -3,32 +3,12 @@ import { Platform, Workflow } from '@expo/eas-build-job';
|
||||
import { BuildProfile, IosVersionAutoIncrement } from '@expo/eas-json';
|
||||
import type { XCBuildConfiguration } from 'xcode';
|
||||
|
||||
import Log from '../../log';
|
||||
import {
|
||||
ensureBundleIdentifierIsDefinedForManagedProjectAsync,
|
||||
warnIfBundleIdentifierDefinedInAppConfigForBareWorkflowProject,
|
||||
} from '../../project/ios/bundleIdentifier';
|
||||
import { resolveWorkflowAsync } from '../../project/workflow';
|
||||
import { ConfigureContext } from '../context';
|
||||
import { isExpoUpdatesInstalled } from '../utils/updates';
|
||||
import { configureUpdatesAsync, syncUpdatesConfigurationAsync } from './UpdatesModule';
|
||||
import { syncUpdatesConfigurationAsync } from './UpdatesModule';
|
||||
import { BumpStrategy, bumpVersionAsync, bumpVersionInAppJsonAsync } from './version';
|
||||
|
||||
export async function configureIosAsync(ctx: ConfigureContext): Promise<void> {
|
||||
if (!ctx.hasIosNativeProject) {
|
||||
await ensureBundleIdentifierIsDefinedForManagedProjectAsync(ctx.projectDir, ctx.exp);
|
||||
return;
|
||||
}
|
||||
|
||||
warnIfBundleIdentifierDefinedInAppConfigForBareWorkflowProject(ctx.projectDir, ctx.exp);
|
||||
|
||||
if (isExpoUpdatesInstalled(ctx.projectDir)) {
|
||||
await configureUpdatesAsync(ctx.projectDir, ctx.exp);
|
||||
}
|
||||
Log.withTick('iOS project configured');
|
||||
}
|
||||
|
||||
export async function validateAndSyncProjectConfigurationAsync({
|
||||
export async function syncProjectConfigurationAsync({
|
||||
projectDir,
|
||||
exp,
|
||||
buildProfile,
|
||||
@@ -6,13 +6,14 @@ import semver from 'semver';
|
||||
import { ora } from '../ora';
|
||||
|
||||
const PLUGIN_PACKAGE_NAME = 'eas-cli-local-build-plugin';
|
||||
const PLUGIN_PACKAGE_VERSION = '0.0.56';
|
||||
const PLUGIN_PACKAGE_VERSION = '0.0.58';
|
||||
|
||||
export interface LocalBuildOptions {
|
||||
enable: boolean;
|
||||
skipCleanup?: boolean;
|
||||
skipNativeBuild?: boolean;
|
||||
artifactsDir?: string;
|
||||
artifactPath?: string;
|
||||
workingdir?: string;
|
||||
verbose?: boolean;
|
||||
}
|
||||
@@ -41,6 +42,7 @@ export async function runLocalBuildAsync(job: Job, options: LocalBuildOptions):
|
||||
: {}),
|
||||
...(options.skipNativeBuild ? { EAS_LOCAL_BUILD_SKIP_NATIVE_BUILD: '1' } : {}),
|
||||
...(options.artifactsDir ? { EAS_LOCAL_BUILD_ARTIFACTS_DIR: options.artifactsDir } : {}),
|
||||
...(options.artifactPath ? { EAS_LOCAL_BUILD_ARTIFACT_PATH: options.artifactPath } : {}),
|
||||
},
|
||||
});
|
||||
childProcess = spawnPromise.child;
|
||||
|
||||
@@ -38,7 +38,6 @@ let sdkVersionChecked = false;
|
||||
|
||||
export interface BuildFlags {
|
||||
requestedPlatform: RequestedPlatform;
|
||||
skipProjectConfiguration: boolean;
|
||||
profile?: string;
|
||||
nonInteractive: boolean;
|
||||
wait: boolean;
|
||||
@@ -53,7 +52,10 @@ export async function runBuildAndSubmitAsync(projectDir: string, flags: BuildFla
|
||||
await getVcsClient().ensureRepoExistsAsync();
|
||||
await ensureRepoIsCleanAsync(flags.nonInteractive);
|
||||
|
||||
await ensureProjectConfiguredAsync(projectDir, flags.requestedPlatform);
|
||||
await ensureProjectConfiguredAsync({
|
||||
projectDir,
|
||||
nonInteractive: flags.nonInteractive,
|
||||
});
|
||||
|
||||
const platforms = toPlatforms(flags.requestedPlatform);
|
||||
const buildProfiles = await getProfilesAsync({
|
||||
@@ -163,7 +165,6 @@ async function prepareAndStartBuildAsync({
|
||||
nonInteractive: flags.nonInteractive,
|
||||
platform: buildProfile.platform,
|
||||
projectDir,
|
||||
skipProjectConfiguration: flags.skipProjectConfiguration,
|
||||
localBuildOptions: flags.localBuildOptions,
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Workflow } from '@expo/eas-build-job';
|
||||
import { error } from '@oclif/errors';
|
||||
import { Errors } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
import resolveFrom from 'resolve-from';
|
||||
|
||||
@@ -64,7 +64,7 @@ export async function ensureExpoDevClientInstalledForDevClientBuildsAsync({
|
||||
if (install) {
|
||||
await installExpoDevClientAsync(projectDir, { nonInteractive });
|
||||
} else {
|
||||
error(`Install ${chalk.bold('expo-dev-client')} manually and come back later.`, {
|
||||
Errors.error(`Install ${chalk.bold('expo-dev-client')} manually and come back later.`, {
|
||||
exit: 1,
|
||||
});
|
||||
}
|
||||
@@ -83,7 +83,7 @@ export async function ensureExpoDevClientInstalledForDevClientBuildsAsync({
|
||||
initial: false,
|
||||
});
|
||||
if (!shouldContinue) {
|
||||
error('Come back later', { exit: 1 });
|
||||
Errors.error('Come back later', { exit: 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { EasJsonReader } from '@expo/eas-json';
|
||||
import { Command } from '@oclif/command';
|
||||
import { Command } from '@oclif/core';
|
||||
import semver from 'semver';
|
||||
|
||||
import {
|
||||
@@ -21,16 +21,19 @@ export default abstract class EasCommand extends Command {
|
||||
* force the user to log in
|
||||
*/
|
||||
protected requiresAuthentication = true;
|
||||
protected mustBeRunInsideProject = true;
|
||||
|
||||
protected abstract runAsync(): Promise<any>;
|
||||
|
||||
// eslint-disable-next-line async-protect/async-suffix
|
||||
async run(): Promise<any> {
|
||||
await initAnalyticsAsync();
|
||||
await this.applyCliConfigAsync();
|
||||
if (this.mustBeRunInsideProject) {
|
||||
await this.applyCliConfigAsync();
|
||||
}
|
||||
|
||||
if (this.requiresAuthentication) {
|
||||
const { flags } = this.parse();
|
||||
const { flags } = await this.parse();
|
||||
const nonInteractive = (flags as any)['non-interactive'] ?? false;
|
||||
await ensureLoggedInAsync({ nonInteractive });
|
||||
} else {
|
||||
|
||||
@@ -6,6 +6,7 @@ export default class AccountLogin extends EasCommand {
|
||||
static description = 'log in with your Expo account';
|
||||
static aliases = ['login'];
|
||||
|
||||
protected mustBeRunInsideProject = false;
|
||||
protected requiresAuthentication = false;
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
|
||||
@@ -6,6 +6,7 @@ export default class AccountLogout extends EasCommand {
|
||||
static description = 'log out';
|
||||
static aliases = ['logout'];
|
||||
|
||||
protected mustBeRunInsideProject = false;
|
||||
protected requiresAuthentication = false;
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
|
||||
@@ -8,6 +8,7 @@ export default class AccountView extends EasCommand {
|
||||
static description = 'show the username you are logged in as';
|
||||
static aliases = ['whoami'];
|
||||
|
||||
protected mustBeRunInsideProject = false;
|
||||
protected requiresAuthentication = false;
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
|
||||
@@ -10,7 +10,7 @@ export default class AnalyticsView extends EasCommand {
|
||||
protected requiresAuthentication = false;
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { STATUS: status } = this.parse(AnalyticsView).args;
|
||||
const { STATUS: status } = (await this.parse(AnalyticsView)).args;
|
||||
if (status) {
|
||||
await UserSettings.setAsync('analyticsEnabled', status === 'on');
|
||||
Log.withTick(`${status === 'on' ? 'Enabling' : 'Disabling'} analytics.`);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
getProjectIdAsync,
|
||||
} from '../../project/projectUtils';
|
||||
import { promptAsync } from '../../prompts';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
import { getVcsClient } from '../../vcs';
|
||||
|
||||
export async function createUpdateBranchOnAppAsync({
|
||||
@@ -51,7 +52,6 @@ export async function createUpdateBranchOnAppAsync({
|
||||
}
|
||||
|
||||
export default class BranchCreate extends EasCommand {
|
||||
static hidden = true;
|
||||
static description = 'Create a branch on the current project.';
|
||||
|
||||
static args = [
|
||||
@@ -63,7 +63,7 @@ export default class BranchCreate extends EasCommand {
|
||||
];
|
||||
|
||||
static flags = {
|
||||
json: flags.boolean({
|
||||
json: Flags.boolean({
|
||||
description: 'return a json with the new branch ID and name.',
|
||||
default: false,
|
||||
}),
|
||||
@@ -73,7 +73,10 @@ export default class BranchCreate extends EasCommand {
|
||||
let {
|
||||
args: { name },
|
||||
flags,
|
||||
} = this.parse(BranchCreate);
|
||||
} = await this.parse(BranchCreate);
|
||||
if (flags.json) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
||||
@@ -99,12 +102,11 @@ export default class BranchCreate extends EasCommand {
|
||||
const newBranch = await createUpdateBranchOnAppAsync({ appId: projectId, name });
|
||||
|
||||
if (flags.json) {
|
||||
Log.log(newBranch);
|
||||
return;
|
||||
printJsonOnlyOutput(newBranch);
|
||||
} else {
|
||||
Log.withTick(
|
||||
`️Created a new branch: ${chalk.bold(newBranch.name)} on project ${chalk.bold(fullName)}.`
|
||||
);
|
||||
}
|
||||
|
||||
Log.withTick(
|
||||
`️Created a new branch: ${chalk.bold(newBranch.name)} on project ${chalk.bold(fullName)}.`
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
getProjectIdAsync,
|
||||
} from '../../project/projectUtils';
|
||||
import { promptAsync, toggleConfirmAsync } from '../../prompts';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
|
||||
async function getBranchInfoAsync({
|
||||
appId,
|
||||
@@ -76,8 +77,7 @@ async function deleteBranchOnAppAsync({
|
||||
}
|
||||
|
||||
export default class BranchDelete extends EasCommand {
|
||||
static hidden = true;
|
||||
static description = 'Republish an update group';
|
||||
static description = 'Delete a branch on the current project';
|
||||
|
||||
static args = [
|
||||
{
|
||||
@@ -87,7 +87,7 @@ export default class BranchDelete extends EasCommand {
|
||||
},
|
||||
];
|
||||
static flags = {
|
||||
json: flags.boolean({
|
||||
json: Flags.boolean({
|
||||
description: `return JSON with the edited branch's ID and name.`,
|
||||
default: false,
|
||||
}),
|
||||
@@ -97,7 +97,10 @@ export default class BranchDelete extends EasCommand {
|
||||
let {
|
||||
args: { name },
|
||||
flags: { json: jsonFlag },
|
||||
} = this.parse(BranchDelete);
|
||||
} = await this.parse(BranchDelete);
|
||||
if (jsonFlag) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
||||
@@ -142,11 +145,11 @@ export default class BranchDelete extends EasCommand {
|
||||
});
|
||||
|
||||
if (jsonFlag) {
|
||||
Log.log(JSON.stringify(deletionResult));
|
||||
printJsonOnlyOutput(deletionResult);
|
||||
} else {
|
||||
Log.withTick(
|
||||
`️Deleted branch "${name}" and all of its updates on project ${chalk.bold(fullName)}.`
|
||||
);
|
||||
}
|
||||
|
||||
Log.withTick(
|
||||
`️Deleted branch "${name}" and all of its updates on project ${chalk.bold(fullName)}.`
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
import CliTable from 'cli-table3';
|
||||
import { print } from 'graphql';
|
||||
@@ -16,6 +16,7 @@ import { UpdateBranchFragmentNode } from '../../graphql/types/UpdateBranch';
|
||||
import Log from '../../log';
|
||||
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
||||
import { UPDATE_COLUMNS, formatUpdate, getPlatformsForGroup } from '../../update/utils';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
|
||||
const BRANCHES_LIMIT = 10_000;
|
||||
|
||||
@@ -54,26 +55,27 @@ export async function listBranchesAsync({
|
||||
}
|
||||
|
||||
export default class BranchList extends EasCommand {
|
||||
static hidden = true;
|
||||
|
||||
static description = 'List all branches on this project.';
|
||||
|
||||
static flags = {
|
||||
json: flags.boolean({
|
||||
json: Flags.boolean({
|
||||
description: 'return output as JSON',
|
||||
default: false,
|
||||
}),
|
||||
};
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { flags } = this.parse(BranchList);
|
||||
const { flags } = await this.parse(BranchList);
|
||||
if (flags.json) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
||||
const projectId = await getProjectIdAsync(exp);
|
||||
const branches = await listBranchesAsync({ projectId });
|
||||
if (flags.json) {
|
||||
Log.log(JSON.stringify(branches, null, 2));
|
||||
printJsonOnlyOutput(branches);
|
||||
} else {
|
||||
const table = new CliTable({
|
||||
head: ['Branch', ...UPDATE_COLUMNS],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
getProjectIdAsync,
|
||||
} from '../../project/projectUtils';
|
||||
import { promptAsync } from '../../prompts';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
|
||||
async function renameUpdateBranchOnAppAsync({
|
||||
appId,
|
||||
@@ -51,19 +52,18 @@ async function renameUpdateBranchOnAppAsync({
|
||||
}
|
||||
|
||||
export default class BranchRename extends EasCommand {
|
||||
static hidden = true;
|
||||
static description = 'Rename a branch.';
|
||||
|
||||
static flags = {
|
||||
from: flags.string({
|
||||
from: Flags.string({
|
||||
description: 'current name of the branch.',
|
||||
required: false,
|
||||
}),
|
||||
to: flags.string({
|
||||
to: Flags.string({
|
||||
description: 'new name of the branch.',
|
||||
required: false,
|
||||
}),
|
||||
json: flags.boolean({
|
||||
json: Flags.boolean({
|
||||
description: `return a json with the edited branch's ID and name.`,
|
||||
default: false,
|
||||
}),
|
||||
@@ -72,7 +72,10 @@ export default class BranchRename extends EasCommand {
|
||||
async runAsync(): Promise<void> {
|
||||
let {
|
||||
flags: { json: jsonFlag, from: currentName, to: newName },
|
||||
} = this.parse(BranchRename);
|
||||
} = await this.parse(BranchRename);
|
||||
if (jsonFlag) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
||||
@@ -112,14 +115,13 @@ export default class BranchRename extends EasCommand {
|
||||
});
|
||||
|
||||
if (jsonFlag) {
|
||||
Log.log(JSON.stringify(editedBranch));
|
||||
return;
|
||||
printJsonOnlyOutput(editedBranch);
|
||||
} else {
|
||||
Log.withTick(
|
||||
`️Renamed branch from ${currentName} to ${chalk.bold(
|
||||
editedBranch.name
|
||||
)} on project ${chalk.bold(fullName)}.`
|
||||
);
|
||||
}
|
||||
|
||||
Log.withTick(
|
||||
`️Renamed branch from ${currentName} to ${chalk.bold(
|
||||
editedBranch.name
|
||||
)} on project ${chalk.bold(fullName)}.`
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,73 +1,19 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
import Table from 'cli-table3';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client';
|
||||
import { ViewBranchQuery, ViewBranchQueryVariables } from '../../graphql/generated';
|
||||
import { UpdateQuery } from '../../graphql/queries/UpdateQuery';
|
||||
import Log from '../../log';
|
||||
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
||||
import { promptAsync } from '../../prompts';
|
||||
import { UPDATE_COLUMNS, formatUpdate, getPlatformsForGroup } from '../../update/utils';
|
||||
import groupBy from '../../utils/expodash/groupBy';
|
||||
import formatFields from '../../utils/formatFields';
|
||||
|
||||
const PAGE_LIMIT = 10_000;
|
||||
|
||||
export async function viewUpdateBranchAsync({
|
||||
appId,
|
||||
name,
|
||||
}: Pick<ViewBranchQueryVariables, 'appId' | 'name'>): Promise<ViewBranchQuery> {
|
||||
const data = await withErrorHandlingAsync(
|
||||
graphqlClient
|
||||
.query<ViewBranchQuery, ViewBranchQueryVariables>(
|
||||
gql`
|
||||
query ViewBranch($appId: String!, $name: String!, $limit: Int!) {
|
||||
app {
|
||||
byId(appId: $appId) {
|
||||
id
|
||||
updateBranchByName(name: $name) {
|
||||
id
|
||||
name
|
||||
updates(offset: 0, limit: $limit) {
|
||||
id
|
||||
group
|
||||
message
|
||||
createdAt
|
||||
runtimeVersion
|
||||
platform
|
||||
manifestFragment
|
||||
actor {
|
||||
id
|
||||
... on User {
|
||||
username
|
||||
}
|
||||
... on Robot {
|
||||
firstName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
{
|
||||
appId,
|
||||
name,
|
||||
limit: PAGE_LIMIT,
|
||||
},
|
||||
{ additionalTypenames: ['UpdateBranch', 'Update'] }
|
||||
)
|
||||
.toPromise()
|
||||
);
|
||||
return data;
|
||||
}
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
|
||||
export default class BranchView extends EasCommand {
|
||||
static hidden = true;
|
||||
static description = 'View a branch.';
|
||||
|
||||
static args = [
|
||||
@@ -79,7 +25,7 @@ export default class BranchView extends EasCommand {
|
||||
];
|
||||
|
||||
static flags = {
|
||||
json: flags.boolean({
|
||||
json: Flags.boolean({
|
||||
description: `return a json with the branch's ID name and recent update groups.`,
|
||||
default: false,
|
||||
}),
|
||||
@@ -89,7 +35,10 @@ export default class BranchView extends EasCommand {
|
||||
let {
|
||||
args: { name },
|
||||
flags: { json: jsonFlag },
|
||||
} = this.parse(BranchView);
|
||||
} = await this.parse(BranchView);
|
||||
if (jsonFlag) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
||||
@@ -108,7 +57,7 @@ export default class BranchView extends EasCommand {
|
||||
}));
|
||||
}
|
||||
|
||||
const { app } = await viewUpdateBranchAsync({
|
||||
const { app } = await UpdateQuery.viewBranchAsync({
|
||||
appId: projectId,
|
||||
name,
|
||||
});
|
||||
@@ -122,37 +71,36 @@ export default class BranchView extends EasCommand {
|
||||
);
|
||||
|
||||
if (jsonFlag) {
|
||||
Log.log(JSON.stringify({ ...UpdateBranch, updates }));
|
||||
return;
|
||||
printJsonOnlyOutput({ ...UpdateBranch, updates });
|
||||
} else {
|
||||
const groupTable = new Table({
|
||||
head: UPDATE_COLUMNS,
|
||||
wordWrap: true,
|
||||
});
|
||||
|
||||
for (const update of updates) {
|
||||
groupTable.push([
|
||||
formatUpdate(update),
|
||||
update.runtimeVersion,
|
||||
update.group,
|
||||
getPlatformsForGroup({
|
||||
updates: UpdateBranch.updates,
|
||||
group: update.group,
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
Log.addNewLineIfNone();
|
||||
Log.log(chalk.bold('Branch:'));
|
||||
Log.log(
|
||||
formatFields([
|
||||
{ label: 'Name', value: UpdateBranch.name },
|
||||
{ label: 'ID', value: UpdateBranch.id },
|
||||
])
|
||||
);
|
||||
Log.addNewLineIfNone();
|
||||
Log.log(chalk.bold('Recently published update groups:'));
|
||||
Log.log(groupTable.toString());
|
||||
}
|
||||
|
||||
const groupTable = new Table({
|
||||
head: UPDATE_COLUMNS,
|
||||
wordWrap: true,
|
||||
});
|
||||
|
||||
for (const update of updates) {
|
||||
groupTable.push([
|
||||
formatUpdate(update),
|
||||
update.runtimeVersion,
|
||||
update.group,
|
||||
getPlatformsForGroup({
|
||||
updates: UpdateBranch.updates,
|
||||
group: update.group,
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
Log.addNewLineIfNone();
|
||||
Log.log(chalk.bold('Branch:'));
|
||||
Log.log(
|
||||
formatFields([
|
||||
{ label: 'Name', value: UpdateBranch.name },
|
||||
{ label: 'ID', value: UpdateBranch.id },
|
||||
])
|
||||
);
|
||||
Log.addNewLineIfNone();
|
||||
Log.log(chalk.bold('Recently published update groups:'));
|
||||
Log.log(groupTable.toString());
|
||||
}
|
||||
}
|
||||
@@ -115,7 +115,7 @@ export default class BuildCancel extends EasCommand {
|
||||
static args = [{ name: 'BUILD_ID' }];
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { BUILD_ID: buildIdFromArg } = this.parse(BuildCancel).args;
|
||||
const { BUILD_ID: buildIdFromArg } = (await this.parse(BuildCancel)).args;
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import { flags } from '@oclif/command';
|
||||
import { getConfig } from '@expo/config';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
|
||||
import { configureAsync } from '../../build/configure';
|
||||
import { syncUpdatesConfigurationAsync as syncAndroidUpdatesConfigurationAsync } from '../../build/android/UpdatesModule';
|
||||
import { cleanUpOldEasBuildGradleScriptAsync } from '../../build/android/syncProjectConfiguration';
|
||||
import { ensureProjectConfiguredAsync } from '../../build/configure';
|
||||
import { syncUpdatesConfigurationAsync as syncIosUpdatesConfigurationAsync } from '../../build/ios/UpdatesModule';
|
||||
import { isExpoUpdatesInstalled } from '../../build/utils/updates';
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import Log, { learnMore } from '../../log';
|
||||
import { RequestedPlatform } from '../../platform';
|
||||
@@ -13,7 +18,7 @@ export default class BuildConfigure extends EasCommand {
|
||||
static description = 'Configure the project to support EAS Build.';
|
||||
|
||||
static flags = {
|
||||
platform: flags.enum({
|
||||
platform: Flags.enum({
|
||||
description: 'Platform to configure',
|
||||
char: 'p',
|
||||
options: ['android', 'ios', 'all'],
|
||||
@@ -21,50 +26,59 @@ export default class BuildConfigure extends EasCommand {
|
||||
};
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { flags } = this.parse(BuildConfigure);
|
||||
const { flags } = await this.parse(BuildConfigure);
|
||||
|
||||
Log.log(
|
||||
'💡 The following process will configure your iOS and/or Android project to be compatible with EAS Build. These changes only apply to your local project files and you can safely revert them at any time.'
|
||||
);
|
||||
Log.newLine();
|
||||
|
||||
await getVcsClient().ensureRepoExistsAsync();
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const expoUpdatesIsInstalled = isExpoUpdatesInstalled(projectDir);
|
||||
|
||||
const platform =
|
||||
(flags.platform as RequestedPlatform | undefined) ?? (await promptForPlatformAsync());
|
||||
|
||||
await configureAsync({
|
||||
platform,
|
||||
projectDir: await findProjectRootAsync(),
|
||||
// clean up old Android configuration
|
||||
if ([RequestedPlatform.Android, RequestedPlatform.All].includes(platform)) {
|
||||
await cleanUpOldEasBuildGradleScriptAsync(projectDir);
|
||||
}
|
||||
|
||||
// ensure eas.json exists
|
||||
Log.newLine();
|
||||
await ensureProjectConfiguredAsync({
|
||||
projectDir,
|
||||
nonInteractive: false,
|
||||
});
|
||||
|
||||
Log.newLine();
|
||||
logSuccess(platform);
|
||||
}
|
||||
}
|
||||
// configure expo-updates
|
||||
if (expoUpdatesIsInstalled) {
|
||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
||||
|
||||
function logSuccess(platform: RequestedPlatform): void {
|
||||
let platformsText = 'iOS and Android projects are';
|
||||
let storesText = 'the Apple App Store or Google Play Store';
|
||||
if ([RequestedPlatform.Android, RequestedPlatform.All].includes(platform)) {
|
||||
await syncAndroidUpdatesConfigurationAsync(projectDir, exp);
|
||||
}
|
||||
|
||||
if (platform === 'android') {
|
||||
platformsText = 'Android project is';
|
||||
storesText = 'the Google Play Store';
|
||||
} else if (platform === 'ios') {
|
||||
platformsText = 'iOS project is';
|
||||
storesText = 'the Apple App Store Connect';
|
||||
}
|
||||
if ([RequestedPlatform.Ios, RequestedPlatform.All].includes(platform)) {
|
||||
await syncIosUpdatesConfigurationAsync(projectDir, exp);
|
||||
}
|
||||
}
|
||||
|
||||
Log.log(`🎉 Your ${platformsText} ready to build.
|
||||
Log.addNewLineIfNone();
|
||||
|
||||
Log.log(`🎉 Your project is ready to build.
|
||||
|
||||
- Run ${chalk.bold('eas build')} when you are ready to create your first build.
|
||||
- Once the build is completed, run ${chalk.bold('eas submit')} to upload the app to ${storesText}
|
||||
- Once the build is completed, run ${chalk.bold('eas submit')} to upload the app to app stores.
|
||||
- ${learnMore('https://docs.expo.dev/build/introduction', {
|
||||
learnMoreMessage: 'Learn more about other capabilities of EAS Build',
|
||||
})}`);
|
||||
learnMoreMessage: 'Learn more about other capabilities of EAS Build',
|
||||
})}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function promptForPlatformAsync(): Promise<RequestedPlatform> {
|
||||
Log.addNewLineIfNone();
|
||||
const { platform } = await promptAsync({
|
||||
type: 'select',
|
||||
message: 'Which platforms would you like to configure for EAS Build?',
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { EasJsonReader } from '@expo/eas-json';
|
||||
import { flags } from '@oclif/command';
|
||||
import { error } from '@oclif/errors';
|
||||
import { Errors, Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
import figures from 'figures';
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
|
||||
import { BuildFlags, runBuildAndSubmitAsync } from '../../build/runBuildAndSubmit';
|
||||
import { ensureRepoIsCleanAsync, reviewAndCommitChangesAsync } from '../../build/utils/repository';
|
||||
@@ -24,6 +24,7 @@ interface RawBuildFlags {
|
||||
profile?: string;
|
||||
'non-interactive': boolean;
|
||||
local: boolean;
|
||||
output?: string;
|
||||
wait: boolean;
|
||||
'clear-cache': boolean;
|
||||
json: boolean;
|
||||
@@ -35,51 +36,54 @@ export default class Build extends EasCommand {
|
||||
static description = 'Start a build';
|
||||
|
||||
static flags = {
|
||||
platform: flags.enum({
|
||||
platform: Flags.enum({
|
||||
char: 'p',
|
||||
options: ['android', 'ios', 'all'],
|
||||
}),
|
||||
'skip-credentials-check': flags.boolean({
|
||||
'skip-credentials-check': Flags.boolean({
|
||||
default: false,
|
||||
hidden: true,
|
||||
}),
|
||||
json: flags.boolean({
|
||||
json: Flags.boolean({
|
||||
description: 'Enable JSON output, non-JSON messages will be printed to stderr',
|
||||
default: false,
|
||||
}),
|
||||
'skip-project-configuration': flags.boolean({
|
||||
'skip-project-configuration': Flags.boolean({
|
||||
default: false,
|
||||
description: 'Skip project configuration',
|
||||
}),
|
||||
profile: flags.string({
|
||||
profile: Flags.string({
|
||||
description:
|
||||
'Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.',
|
||||
helpValue: 'PROFILE_NAME',
|
||||
}),
|
||||
'non-interactive': flags.boolean({
|
||||
'non-interactive': Flags.boolean({
|
||||
default: false,
|
||||
description: 'Run command in non-interactive mode',
|
||||
}),
|
||||
local: flags.boolean({
|
||||
local: Flags.boolean({
|
||||
default: false,
|
||||
description: 'Run build locally [experimental]',
|
||||
}),
|
||||
wait: flags.boolean({
|
||||
output: Flags.string({
|
||||
description: 'Output path for local build',
|
||||
}),
|
||||
wait: Flags.boolean({
|
||||
default: true,
|
||||
allowNo: true,
|
||||
description: 'Wait for build(s) to complete',
|
||||
}),
|
||||
'clear-cache': flags.boolean({
|
||||
'clear-cache': Flags.boolean({
|
||||
default: false,
|
||||
description: 'Clear cache before the build',
|
||||
}),
|
||||
'auto-submit': flags.boolean({
|
||||
'auto-submit': Flags.boolean({
|
||||
default: false,
|
||||
description:
|
||||
'Submit on build complete using the submit profile with the same name as the build profile',
|
||||
exclusive: ['auto-submit-with-profile'],
|
||||
}),
|
||||
'auto-submit-with-profile': flags.string({
|
||||
'auto-submit-with-profile': Flags.string({
|
||||
description: 'Submit on build complete using the submit profile with provided name',
|
||||
helpValue: 'PROFILE_NAME',
|
||||
exclusive: ['auto-submit'],
|
||||
@@ -87,7 +91,7 @@ export default class Build extends EasCommand {
|
||||
};
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { flags: rawFlags } = this.parse(Build);
|
||||
const { flags: rawFlags } = await this.parse(Build);
|
||||
if (rawFlags.json) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
@@ -101,24 +105,29 @@ export default class Build extends EasCommand {
|
||||
|
||||
private async sanitizeFlagsAsync(flags: RawBuildFlags): Promise<BuildFlags> {
|
||||
const nonInteractive = flags['non-interactive'];
|
||||
if (!flags.local && flags.output) {
|
||||
Errors.error('--output is allowed only for local builds', { exit: 1 });
|
||||
}
|
||||
if (!flags.platform && nonInteractive) {
|
||||
error('--platform is required when building in non-interactive mode', { exit: 1 });
|
||||
Errors.error('--platform is required when building in non-interactive mode', { exit: 1 });
|
||||
}
|
||||
if (flags.json && !nonInteractive) {
|
||||
error('--json is allowed only when building in non-interactive mode', { exit: 1 });
|
||||
Errors.error('--json is allowed only when building in non-interactive mode', { exit: 1 });
|
||||
}
|
||||
|
||||
const requestedPlatform = await selectRequestedPlatformAsync(flags.platform);
|
||||
if (flags.local) {
|
||||
if (flags['auto-submit'] || flags['auto-submit-with-profile'] !== undefined) {
|
||||
// TODO: implement this
|
||||
error('Auto-submits are not yet supported when building locally', { exit: 1 });
|
||||
Errors.error('Auto-submits are not yet supported when building locally', { exit: 1 });
|
||||
}
|
||||
|
||||
if (requestedPlatform === RequestedPlatform.All) {
|
||||
error('Builds for multiple platforms are not supported with flag --local', { exit: 1 });
|
||||
Errors.error('Builds for multiple platforms are not supported with flag --local', {
|
||||
exit: 1,
|
||||
});
|
||||
} else if (process.platform !== 'darwin' && requestedPlatform === RequestedPlatform.Ios) {
|
||||
error('Unsupported platform, macOS is required to build apps for iOS', { exit: 1 });
|
||||
Errors.error('Unsupported platform, macOS is required to build apps for iOS', { exit: 1 });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,11 +142,14 @@ export default class Build extends EasCommand {
|
||||
const profile = flags['profile'];
|
||||
return {
|
||||
requestedPlatform,
|
||||
skipProjectConfiguration: flags['skip-project-configuration'],
|
||||
profile,
|
||||
nonInteractive,
|
||||
localBuildOptions: flags['local']
|
||||
? { enable: true, verbose: true }
|
||||
? {
|
||||
enable: true,
|
||||
verbose: true,
|
||||
artifactPath: flags.output && path.resolve(process.cwd(), flags.output),
|
||||
}
|
||||
: {
|
||||
enable: false,
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
@@ -29,51 +29,60 @@ export default class BuildInspect extends EasCommand {
|
||||
'Inspect the state of the project at specific build stages. Useful for troubleshooting.';
|
||||
|
||||
static flags = {
|
||||
platform: flags.enum({
|
||||
platform: Flags.enum({
|
||||
char: 'p',
|
||||
options: [RequestedPlatform.Android, RequestedPlatform.Ios],
|
||||
required: true,
|
||||
}),
|
||||
profile: flags.string({
|
||||
profile: Flags.string({
|
||||
description:
|
||||
'Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.',
|
||||
helpValue: 'PROFILE_NAME',
|
||||
}),
|
||||
stage: flags.enum({
|
||||
stage: Flags.enum({
|
||||
char: 's',
|
||||
description: STAGE_DESCRIPTION,
|
||||
options: [InspectStage.ARCHIVE, InspectStage.PRE_BUILD, InspectStage.POST_BUILD],
|
||||
required: true,
|
||||
}),
|
||||
output: flags.string({
|
||||
output: Flags.string({
|
||||
char: 'o',
|
||||
description: 'Output directory.',
|
||||
required: true,
|
||||
helpValue: 'OUTPUT_DIRECTORY',
|
||||
}),
|
||||
force: flags.boolean({
|
||||
force: Flags.boolean({
|
||||
description: 'Delete OUTPUT_DIRECTORY if it already exists.',
|
||||
default: false,
|
||||
}),
|
||||
verbose: flags.boolean({
|
||||
verbose: Flags.boolean({
|
||||
char: 'v',
|
||||
default: false,
|
||||
}),
|
||||
};
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { flags } = this.parse(BuildInspect);
|
||||
const { flags } = await this.parse(BuildInspect);
|
||||
const outputDirectory = path.resolve(process.cwd(), flags.output);
|
||||
const tmpWorkingdir = path.join(getTmpDirectory(), uuidv4());
|
||||
|
||||
if (flags.force && process.cwd().startsWith(outputDirectory)) {
|
||||
throw new Error(
|
||||
`This operation is not allowed, it would delete all files in ${outputDirectory} including the current project.`
|
||||
);
|
||||
}
|
||||
|
||||
await this.prepareOutputDirAsync(outputDirectory, flags.force);
|
||||
|
||||
if (flags.stage === InspectStage.ARCHIVE) {
|
||||
const vcs = getVcsClient();
|
||||
await vcs.ensureRepoExistsAsync();
|
||||
await vcs.makeShallowCopyAsync(outputDirectory);
|
||||
Log.withTick(`Project saved to ${outputDirectory}`);
|
||||
await vcs.makeShallowCopyAsync(tmpWorkingdir);
|
||||
await this.copyToOutputDirAsync(tmpWorkingdir, outputDirectory);
|
||||
} else {
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const tmpWorkingdir = path.join(getTmpDirectory(), uuidv4());
|
||||
try {
|
||||
await runBuildAndSubmitAsync(projectDir, {
|
||||
skipProjectConfiguration: false,
|
||||
nonInteractive: false,
|
||||
wait: true,
|
||||
clearCache: false,
|
||||
@@ -99,18 +108,7 @@ export default class BuildInspect extends EasCommand {
|
||||
Log.error(`Re-run this command with ${chalk.bold('--verbose')} flag to see the logs`);
|
||||
}
|
||||
} finally {
|
||||
const spinner = ora().start(`Copying project build directory to ${outputDirectory}`);
|
||||
try {
|
||||
const tmpBuildDirectory = path.join(tmpWorkingdir, 'build');
|
||||
if (await fs.pathExists(tmpBuildDirectory)) {
|
||||
await fs.copy(tmpBuildDirectory, outputDirectory);
|
||||
}
|
||||
await fs.remove(tmpWorkingdir);
|
||||
spinner.succeed(`Project build directory saved to ${outputDirectory}`);
|
||||
} catch (err) {
|
||||
spinner.fail();
|
||||
throw err;
|
||||
}
|
||||
await this.copyToOutputDirAsync(path.join(tmpWorkingdir, 'build'), outputDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,4 +123,18 @@ export default class BuildInspect extends EasCommand {
|
||||
}
|
||||
await fs.mkdirp(outputDir);
|
||||
}
|
||||
|
||||
private async copyToOutputDirAsync(src: string, dst: string): Promise<void> {
|
||||
const spinner = ora().start(`Copying project directory to ${dst}`);
|
||||
try {
|
||||
if (await fs.pathExists(src)) {
|
||||
await fs.copy(src, dst);
|
||||
}
|
||||
await fs.remove(src);
|
||||
spinner.succeed(`Project directory saved to ${dst}`);
|
||||
} catch (err) {
|
||||
spinner.fail();
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
|
||||
import { BuildDistributionType, BuildStatus } from '../../build/types';
|
||||
@@ -25,13 +25,13 @@ export default class BuildList extends EasCommand {
|
||||
static description = 'list all builds for your project';
|
||||
|
||||
static flags = {
|
||||
platform: flags.enum({
|
||||
platform: Flags.enum({
|
||||
options: [RequestedPlatform.All, RequestedPlatform.Android, RequestedPlatform.Ios],
|
||||
}),
|
||||
json: flags.boolean({
|
||||
json: Flags.boolean({
|
||||
description: 'Enable JSON output, non-JSON messages will be printed to stderr',
|
||||
}),
|
||||
status: flags.enum({
|
||||
status: Flags.enum({
|
||||
options: [
|
||||
BuildStatus.NEW,
|
||||
BuildStatus.IN_QUEUE,
|
||||
@@ -41,26 +41,26 @@ export default class BuildList extends EasCommand {
|
||||
BuildStatus.CANCELED,
|
||||
],
|
||||
}),
|
||||
distribution: flags.enum({
|
||||
distribution: Flags.enum({
|
||||
options: [
|
||||
BuildDistributionType.STORE,
|
||||
BuildDistributionType.INTERNAL,
|
||||
BuildDistributionType.SIMULATOR,
|
||||
],
|
||||
}),
|
||||
channel: flags.string(),
|
||||
appVersion: flags.string(),
|
||||
appBuildVersion: flags.string(),
|
||||
sdkVersion: flags.string(),
|
||||
runtimeVersion: flags.string(),
|
||||
appIdentifier: flags.string(),
|
||||
buildProfile: flags.string(),
|
||||
gitCommitHash: flags.string(),
|
||||
limit: flags.integer(),
|
||||
channel: Flags.string(),
|
||||
appVersion: Flags.string(),
|
||||
appBuildVersion: Flags.string(),
|
||||
sdkVersion: Flags.string(),
|
||||
runtimeVersion: Flags.string(),
|
||||
appIdentifier: Flags.string(),
|
||||
buildProfile: Flags.string(),
|
||||
gitCommitHash: Flags.string(),
|
||||
limit: Flags.integer(),
|
||||
};
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { flags } = this.parse(BuildList);
|
||||
const { flags } = await this.parse(BuildList);
|
||||
const {
|
||||
json,
|
||||
platform: requestedPlatform,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
|
||||
import { formatGraphQLBuild } from '../../build/utils/formatBuild';
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
@@ -20,7 +20,7 @@ export default class BuildView extends EasCommand {
|
||||
static args = [{ name: 'BUILD_ID' }];
|
||||
|
||||
static flags = {
|
||||
json: flags.boolean({
|
||||
json: Flags.boolean({
|
||||
description: 'Enable JSON output, non-JSON messages will be printed to stderr',
|
||||
}),
|
||||
};
|
||||
@@ -29,7 +29,7 @@ export default class BuildView extends EasCommand {
|
||||
const {
|
||||
args: { BUILD_ID: buildId },
|
||||
flags,
|
||||
} = this.parse(BuildView);
|
||||
} = await this.parse(BuildView);
|
||||
if (flags.json) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
} from '../../project/projectUtils';
|
||||
import { promptAsync } from '../../prompts';
|
||||
import formatFields from '../../utils/formatFields';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
import { createUpdateBranchOnAppAsync } from '../branch/create';
|
||||
|
||||
export async function createUpdateChannelOnAppAsync({
|
||||
@@ -59,7 +60,6 @@ export async function createUpdateChannelOnAppAsync({
|
||||
}
|
||||
|
||||
export default class ChannelCreate extends EasCommand {
|
||||
static hidden = true;
|
||||
static description = 'Create a channel on the current project.';
|
||||
|
||||
static args = [
|
||||
@@ -71,7 +71,7 @@ export default class ChannelCreate extends EasCommand {
|
||||
];
|
||||
|
||||
static flags = {
|
||||
json: flags.boolean({
|
||||
json: Flags.boolean({
|
||||
description:
|
||||
'print output as a JSON object with the new channel ID, name and branch mapping.',
|
||||
default: false,
|
||||
@@ -82,7 +82,10 @@ export default class ChannelCreate extends EasCommand {
|
||||
let {
|
||||
args: { name: channelName },
|
||||
flags: { json: jsonFlag },
|
||||
} = this.parse(ChannelCreate);
|
||||
} = await this.parse(ChannelCreate);
|
||||
if (jsonFlag) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
||||
@@ -134,30 +137,29 @@ export default class ChannelCreate extends EasCommand {
|
||||
}
|
||||
|
||||
if (jsonFlag) {
|
||||
Log.log(JSON.stringify(newChannel));
|
||||
return;
|
||||
printJsonOnlyOutput(newChannel);
|
||||
} else {
|
||||
Log.addNewLineIfNone();
|
||||
Log.withTick(
|
||||
`Created a new channel on project ${chalk.bold(await getProjectFullNameAsync(exp))}`
|
||||
);
|
||||
Log.log(
|
||||
formatFields([
|
||||
{ label: 'Name', value: newChannel.name },
|
||||
{ label: 'ID', value: newChannel.id },
|
||||
])
|
||||
);
|
||||
Log.addNewLineIfNone();
|
||||
Log.withTick(`${branchMessage} and have pointed the channel at it.`);
|
||||
Log.log(
|
||||
formatFields([
|
||||
{ label: 'Name', value: newChannel.name },
|
||||
{ label: 'ID', value: branchId },
|
||||
])
|
||||
);
|
||||
|
||||
Log.addNewLineIfNone();
|
||||
Log.log(chalk.bold('You can now update your app by publishing!'));
|
||||
}
|
||||
|
||||
Log.addNewLineIfNone();
|
||||
Log.withTick(
|
||||
`Created a new channel on project ${chalk.bold(await getProjectFullNameAsync(exp))}`
|
||||
);
|
||||
Log.log(
|
||||
formatFields([
|
||||
{ label: 'Name', value: newChannel.name },
|
||||
{ label: 'ID', value: newChannel.id },
|
||||
])
|
||||
);
|
||||
Log.addNewLineIfNone();
|
||||
Log.withTick(`${branchMessage} and have pointed the channel at it.`);
|
||||
Log.log(
|
||||
formatFields([
|
||||
{ label: 'Name', value: newChannel.name },
|
||||
{ label: 'ID', value: branchId },
|
||||
])
|
||||
);
|
||||
|
||||
Log.addNewLineIfNone();
|
||||
Log.log(chalk.bold('You can now update your app by publishing!'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { Flags } from '@oclif/core';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client';
|
||||
import {
|
||||
DeleteUpdateChannelMutation,
|
||||
DeleteUpdateChannelMutationVariables,
|
||||
DeleteUpdateChannelResult,
|
||||
GetChannelInfoQuery,
|
||||
GetChannelInfoQueryVariables,
|
||||
} from '../../graphql/generated';
|
||||
import Log from '../../log';
|
||||
import {
|
||||
findProjectRootAsync,
|
||||
getProjectFullNameAsync,
|
||||
getProjectIdAsync,
|
||||
} from '../../project/projectUtils';
|
||||
import { promptAsync, toggleConfirmAsync } from '../../prompts';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
|
||||
export default class ChannelDelete extends EasCommand {
|
||||
static hidden = true;
|
||||
static description = 'Delete a channel on the current project';
|
||||
|
||||
static args = [
|
||||
{
|
||||
name: 'name',
|
||||
required: false,
|
||||
description: 'Name of the channel to delete',
|
||||
},
|
||||
];
|
||||
static flags = {
|
||||
json: Flags.boolean({
|
||||
description: `Delete a channel on the current project`,
|
||||
default: false,
|
||||
}),
|
||||
'non-interactive': Flags.boolean({
|
||||
default: false,
|
||||
description: 'Run command in non-interactive mode',
|
||||
}),
|
||||
};
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const {
|
||||
args: { name: nameArg },
|
||||
flags: { json: jsonFlag, 'non-interactive': nonInteractiveFlag },
|
||||
} = await this.parse(ChannelDelete);
|
||||
if (jsonFlag && !nonInteractiveFlag) {
|
||||
throw new Error('--json is allowed only in non-interactive mode');
|
||||
}
|
||||
if (jsonFlag) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
||||
const fullName = await getProjectFullNameAsync(exp);
|
||||
const projectId = await getProjectIdAsync(exp);
|
||||
|
||||
let name;
|
||||
if (nameArg) {
|
||||
name = nameArg;
|
||||
} else {
|
||||
if (nonInteractiveFlag) {
|
||||
throw new Error('Channel name must be set when running in non-interactive mode');
|
||||
}
|
||||
name = (
|
||||
await promptAsync({
|
||||
type: 'text',
|
||||
name: 'name',
|
||||
message: 'Please enter the name of the channel to delete:',
|
||||
validate: (value: any) => (value ? true : 'Channel name may not be empty.'),
|
||||
})
|
||||
).name;
|
||||
}
|
||||
|
||||
const data = await getChannelInfoAsync({ appId: projectId, name });
|
||||
const channelId = data.app?.byId.updateChannelByName?.id;
|
||||
if (!channelId) {
|
||||
throw new Error(`Could not find channel ${name} on ${fullName}`);
|
||||
}
|
||||
|
||||
if (!nonInteractiveFlag) {
|
||||
Log.addNewLineIfNone();
|
||||
Log.warn(
|
||||
`You are about to permamently delete channel: "${name}".\nThis action is irreversible.`
|
||||
);
|
||||
Log.newLine();
|
||||
const confirmed = await toggleConfirmAsync({ message: 'Are you sure you wish to proceed?' });
|
||||
if (!confirmed) {
|
||||
Log.error(`Canceled deletion of channel: "${name}".`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const deletionResult = await deleteChannelOnAppAsync({
|
||||
channelId,
|
||||
});
|
||||
|
||||
if (jsonFlag) {
|
||||
printJsonOnlyOutput(deletionResult);
|
||||
} else {
|
||||
Log.withTick(`️Deleted channel "${name}".`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getChannelInfoAsync({
|
||||
appId,
|
||||
name,
|
||||
}: GetChannelInfoQueryVariables): Promise<GetChannelInfoQuery> {
|
||||
const data = await withErrorHandlingAsync(
|
||||
graphqlClient
|
||||
.query<GetChannelInfoQuery, GetChannelInfoQueryVariables>(
|
||||
gql`
|
||||
query GetChannelInfo($appId: String!, $name: String!) {
|
||||
app {
|
||||
byId(appId: $appId) {
|
||||
id
|
||||
updateChannelByName(name: $name) {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
{
|
||||
appId,
|
||||
name,
|
||||
},
|
||||
{ additionalTypenames: ['UpdateChannel'] }
|
||||
)
|
||||
.toPromise()
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
async function deleteChannelOnAppAsync({
|
||||
channelId,
|
||||
}: DeleteUpdateChannelMutationVariables): Promise<DeleteUpdateChannelResult> {
|
||||
const data = await withErrorHandlingAsync(
|
||||
graphqlClient
|
||||
.mutation<DeleteUpdateChannelMutation, DeleteUpdateChannelMutationVariables>(
|
||||
gql`
|
||||
mutation DeleteUpdateChannel($channelId: ID!) {
|
||||
updateChannel {
|
||||
deleteUpdateChannel(channelId: $channelId) {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
{
|
||||
channelId,
|
||||
}
|
||||
)
|
||||
.toPromise()
|
||||
);
|
||||
return data.updateChannel.deleteUpdateChannel;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
getProjectIdAsync,
|
||||
} from '../../project/projectUtils';
|
||||
import { promptAsync } from '../../prompts';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
|
||||
async function getChannelByNameForAppAsync({
|
||||
appId,
|
||||
@@ -95,7 +96,6 @@ export async function updateChannelBranchMappingAsync({
|
||||
}
|
||||
|
||||
export default class ChannelEdit extends EasCommand {
|
||||
static hidden = true;
|
||||
static description = 'Point a channel at a new branch.';
|
||||
|
||||
static args = [
|
||||
@@ -107,10 +107,10 @@ export default class ChannelEdit extends EasCommand {
|
||||
];
|
||||
|
||||
static flags = {
|
||||
branch: flags.string({
|
||||
branch: Flags.string({
|
||||
description: 'Name of the branch to point to',
|
||||
}),
|
||||
json: flags.boolean({
|
||||
json: Flags.boolean({
|
||||
description: 'print output as a JSON object with the channel ID, name and branch mapping.',
|
||||
default: false,
|
||||
}),
|
||||
@@ -120,7 +120,10 @@ export default class ChannelEdit extends EasCommand {
|
||||
let {
|
||||
args: { name: channelName },
|
||||
flags: { branch: branchName, json: jsonFlag },
|
||||
} = this.parse(ChannelEdit);
|
||||
} = await this.parse(ChannelEdit);
|
||||
if (jsonFlag) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
||||
@@ -170,16 +173,15 @@ export default class ChannelEdit extends EasCommand {
|
||||
});
|
||||
|
||||
if (jsonFlag) {
|
||||
Log.log(JSON.stringify(channel));
|
||||
return;
|
||||
printJsonOnlyOutput(channel);
|
||||
} else {
|
||||
Log.withTick(
|
||||
chalk`Channel {bold ${channel.name}} is now set to branch {bold ${branch.name}}.\n`
|
||||
);
|
||||
Log.addNewLineIfNone();
|
||||
Log.log(
|
||||
chalk`Users with builds on channel {bold ${channel.name}} will now receive the active update on {bold ${branch.name}}.`
|
||||
);
|
||||
}
|
||||
|
||||
Log.withTick(
|
||||
chalk`Channel {bold ${channel.name}} is now set to branch {bold ${branch.name}}.\n`
|
||||
);
|
||||
Log.addNewLineIfNone();
|
||||
Log.log(
|
||||
chalk`Users with builds on channel {bold ${channel.name}} will now receive the active update on {bold ${branch.name}}.`
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
import Log from '../../log';
|
||||
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
||||
import formatFields from '../../utils/formatFields';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
import { logChannelDetails } from './view';
|
||||
|
||||
const CHANNEL_LIMIT = 10_000;
|
||||
@@ -66,11 +67,10 @@ async function getAllUpdateChannelForAppAsync({
|
||||
}
|
||||
|
||||
export default class ChannelList extends EasCommand {
|
||||
static hidden = true;
|
||||
static description = 'List all channels on the current project.';
|
||||
|
||||
static flags = {
|
||||
json: flags.boolean({
|
||||
json: Flags.boolean({
|
||||
description: 'print output as a JSON object with the channel ID, name and branch mapping.',
|
||||
default: false,
|
||||
}),
|
||||
@@ -79,7 +79,10 @@ export default class ChannelList extends EasCommand {
|
||||
async runAsync(): Promise<void> {
|
||||
const {
|
||||
flags: { json: jsonFlag },
|
||||
} = this.parse(ChannelList);
|
||||
} = await this.parse(ChannelList);
|
||||
if (jsonFlag) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
||||
@@ -94,19 +97,18 @@ export default class ChannelList extends EasCommand {
|
||||
}
|
||||
|
||||
if (jsonFlag) {
|
||||
Log.log(JSON.stringify(channels));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const channel of channels) {
|
||||
Log.addNewLineIfNone();
|
||||
Log.log(
|
||||
formatFields([
|
||||
{ label: 'Name', value: channel.name },
|
||||
{ label: 'ID', value: channel.id },
|
||||
])
|
||||
);
|
||||
logChannelDetails(channel);
|
||||
printJsonOnlyOutput(channels);
|
||||
} else {
|
||||
for (const channel of channels) {
|
||||
Log.addNewLineIfNone();
|
||||
Log.log(
|
||||
formatFields([
|
||||
{ label: 'Name', value: channel.name },
|
||||
{ label: 'ID', value: channel.id },
|
||||
])
|
||||
);
|
||||
logChannelDetails(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
getProjectIdAsync,
|
||||
} from '../../project/projectUtils';
|
||||
import { promptAsync, selectAsync } from '../../prompts';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
import { updateChannelBranchMappingAsync } from './edit';
|
||||
import { BranchMapping, getBranchMapping, getUpdateChannelByNameForAppAsync } from './view';
|
||||
|
||||
@@ -319,19 +320,19 @@ export default class ChannelRollout extends EasCommand {
|
||||
];
|
||||
|
||||
static flags = {
|
||||
branch: flags.string({
|
||||
branch: Flags.string({
|
||||
description: 'branch to rollout',
|
||||
required: false,
|
||||
}),
|
||||
percent: flags.integer({
|
||||
percent: Flags.integer({
|
||||
description: 'percent of traffic to redirect to the new branch',
|
||||
required: false,
|
||||
}),
|
||||
end: flags.boolean({
|
||||
end: Flags.boolean({
|
||||
description: 'end the rollout',
|
||||
default: false,
|
||||
}),
|
||||
json: flags.boolean({
|
||||
json: Flags.boolean({
|
||||
description: 'print output as a JSON object with the new channel ID, name and branch mapping',
|
||||
default: false,
|
||||
}),
|
||||
@@ -340,11 +341,11 @@ export default class ChannelRollout extends EasCommand {
|
||||
async runAsync(): Promise<void> {
|
||||
const {
|
||||
args: { channel: channelName },
|
||||
flags: { json: jsonFlag, end: endFlag },
|
||||
} = this.parse(ChannelRollout);
|
||||
const {
|
||||
flags: { branch: branchName, percent },
|
||||
} = this.parse(ChannelRollout);
|
||||
flags: { json: jsonFlag, end: endFlag, branch: branchName, percent },
|
||||
} = await this.parse(ChannelRollout);
|
||||
if (jsonFlag) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
||||
@@ -420,9 +421,9 @@ export default class ChannelRollout extends EasCommand {
|
||||
}
|
||||
const { newChannelInfo, logMessage } = rolloutMutationResult;
|
||||
if (jsonFlag) {
|
||||
Log.log(JSON.stringify(newChannelInfo));
|
||||
return;
|
||||
printJsonOnlyOutput(newChannelInfo);
|
||||
} else {
|
||||
Log.withTick(logMessage);
|
||||
}
|
||||
Log.withTick(logMessage);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
import assert from 'assert';
|
||||
import chalk from 'chalk';
|
||||
import Table from 'cli-table3';
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
getPlatformsForGroup,
|
||||
} from '../../update/utils';
|
||||
import formatFields from '../../utils/formatFields';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
|
||||
export type BranchMapping = {
|
||||
version: number;
|
||||
@@ -192,7 +193,6 @@ export function logChannelDetails(channel: {
|
||||
}
|
||||
|
||||
export default class ChannelView extends EasCommand {
|
||||
static hidden = true;
|
||||
static description = 'View a channel on the current project.';
|
||||
|
||||
static args = [
|
||||
@@ -204,7 +204,7 @@ export default class ChannelView extends EasCommand {
|
||||
];
|
||||
|
||||
static flags = {
|
||||
json: flags.boolean({
|
||||
json: Flags.boolean({
|
||||
description: 'print output as a JSON object with the channel ID, name and branch mapping.',
|
||||
default: false,
|
||||
}),
|
||||
@@ -214,7 +214,10 @@ export default class ChannelView extends EasCommand {
|
||||
let {
|
||||
args: { name: channelName },
|
||||
flags: { json: jsonFlag },
|
||||
} = this.parse(ChannelView);
|
||||
} = await this.parse(ChannelView);
|
||||
if (jsonFlag) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
||||
@@ -243,20 +246,19 @@ export default class ChannelView extends EasCommand {
|
||||
}
|
||||
|
||||
if (jsonFlag) {
|
||||
Log.log(JSON.stringify(channel));
|
||||
return;
|
||||
printJsonOnlyOutput(channel);
|
||||
} else {
|
||||
Log.addNewLineIfNone();
|
||||
Log.log(chalk.bold('Channel:'));
|
||||
Log.log(
|
||||
formatFields([
|
||||
{ label: 'Name', value: channel.name },
|
||||
{ label: 'ID', value: channel.id },
|
||||
])
|
||||
);
|
||||
Log.addNewLineIfNone();
|
||||
Log.log(chalk`{bold Branches pointed at this channel and their most recent update group:}`);
|
||||
logChannelDetails(channel);
|
||||
}
|
||||
|
||||
Log.addNewLineIfNone();
|
||||
Log.log(chalk.bold('Channel:'));
|
||||
Log.log(
|
||||
formatFields([
|
||||
{ label: 'Name', value: channel.name },
|
||||
{ label: 'ID', value: channel.id },
|
||||
])
|
||||
);
|
||||
Log.addNewLineIfNone();
|
||||
Log.log(chalk`{bold Branches pointed at this channel and their most recent update group:}`);
|
||||
logChannelDetails(channel);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { getProjectConfigDescription } from '@expo/config';
|
||||
import { Platform } from '@expo/eas-build-job';
|
||||
import { EasJsonReader } from '@expo/eas-json';
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
|
||||
import EasCommand from '../commandUtils/EasCommand';
|
||||
import Log from '../log';
|
||||
@@ -14,14 +14,14 @@ export default class Config extends EasCommand {
|
||||
static description = 'show the eas.json config';
|
||||
|
||||
static flags = {
|
||||
platform: flags.enum({ char: 'p', options: ['android', 'ios'] }),
|
||||
profile: flags.string(),
|
||||
platform: Flags.enum({ char: 'p', options: ['android', 'ios'] }),
|
||||
profile: Flags.string(),
|
||||
};
|
||||
|
||||
protected requiresAuthentication = false;
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { flags } = this.parse(Config);
|
||||
const { flags } = await this.parse(Config);
|
||||
const { platform: maybePlatform, profile: maybeProfile } = flags as {
|
||||
platform?: Platform;
|
||||
profile?: string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
import assert from 'assert';
|
||||
import chalk from 'chalk';
|
||||
|
||||
@@ -16,11 +16,11 @@ export default class BuildList extends EasCommand {
|
||||
static description = 'list all registered devices for your account';
|
||||
|
||||
static flags = {
|
||||
'apple-team-id': flags.string(),
|
||||
'apple-team-id': Flags.string(),
|
||||
};
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
let appleTeamIdentifier = this.parse(BuildList).flags['apple-team-id'];
|
||||
let appleTeamIdentifier = (await this.parse(BuildList)).flags['apple-team-id'];
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
||||
|
||||
@@ -13,7 +13,7 @@ export default class DeviceView extends EasCommand {
|
||||
static args = [{ name: 'UDID' }];
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { UDID } = this.parse(DeviceView).args;
|
||||
const { UDID } = (await this.parse(DeviceView)).args;
|
||||
|
||||
if (!UDID) {
|
||||
Log.log(
|
||||
|
||||
@@ -28,6 +28,7 @@ export default class Diagnostics extends EasCommand {
|
||||
'react-navigation',
|
||||
'@expo/webpack-config',
|
||||
'expo-dev-client',
|
||||
'expo-updates',
|
||||
],
|
||||
npmGlobalPackages: ['eas-cli', 'expo-cli'],
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
@@ -23,18 +23,18 @@ export default class EnvironmentSecretCreate extends EasCommand {
|
||||
static description = 'Create an environment secret on the current project or owner account.';
|
||||
|
||||
static flags = {
|
||||
scope: flags.enum({
|
||||
scope: Flags.enum({
|
||||
description: 'Scope for the secret',
|
||||
options: [EnvironmentSecretScope.ACCOUNT, EnvironmentSecretScope.PROJECT],
|
||||
default: EnvironmentSecretScope.PROJECT,
|
||||
}),
|
||||
name: flags.string({
|
||||
name: Flags.string({
|
||||
description: 'Name of the secret',
|
||||
}),
|
||||
value: flags.string({
|
||||
value: Flags.string({
|
||||
description: 'Value of the secret',
|
||||
}),
|
||||
force: flags.boolean({
|
||||
force: Flags.boolean({
|
||||
description: 'Delete and recreate existing secrets',
|
||||
default: false,
|
||||
}),
|
||||
@@ -44,7 +44,7 @@ export default class EnvironmentSecretCreate extends EasCommand {
|
||||
const actor = await ensureLoggedInAsync();
|
||||
let {
|
||||
flags: { name, value: secretValue, scope, force },
|
||||
} = this.parse(EnvironmentSecretCreate);
|
||||
} = await this.parse(EnvironmentSecretCreate);
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
@@ -22,7 +22,7 @@ export default class EnvironmentSecretDelete extends EasCommand {
|
||||
Unsure where to find the secret's ID? Run ${chalk.bold('eas secret:list')}`;
|
||||
|
||||
static flags = {
|
||||
id: flags.string({
|
||||
id: Flags.string({
|
||||
description: 'ID of the secret to delete',
|
||||
}),
|
||||
};
|
||||
@@ -35,7 +35,7 @@ Unsure where to find the secret's ID? Run ${chalk.bold('eas secret:list')}`;
|
||||
|
||||
let {
|
||||
flags: { id },
|
||||
} = this.parse(EnvironmentSecretDelete);
|
||||
} = await this.parse(EnvironmentSecretDelete);
|
||||
let secret: EnvironmentSecretWithScope | undefined;
|
||||
|
||||
if (!id) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { flags } from '@oclif/command';
|
||||
import { error } from '@oclif/errors';
|
||||
import { Errors, Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
|
||||
import EasCommand from '../commandUtils/EasCommand';
|
||||
@@ -20,7 +19,7 @@ import { submitAsync, waitToCompleteAsync } from '../submit/submit';
|
||||
import { printSubmissionDetailsUrls } from '../submit/utils/urls';
|
||||
import { getProfilesAsync } from '../utils/profiles';
|
||||
|
||||
interface RawFlags {
|
||||
interface RawCommandFlags {
|
||||
platform?: string;
|
||||
profile?: string;
|
||||
latest?: boolean;
|
||||
@@ -32,7 +31,7 @@ interface RawFlags {
|
||||
'non-interactive': boolean;
|
||||
}
|
||||
|
||||
interface Flags {
|
||||
interface CommandFlags {
|
||||
requestedPlatform: RequestedPlatform;
|
||||
profile?: string;
|
||||
archiveFlags: SubmitArchiveFlags;
|
||||
@@ -47,47 +46,47 @@ See how to configure submits with eas.json: ${link('https://docs.expo.dev/submit
|
||||
static aliases = ['build:submit'];
|
||||
|
||||
static flags = {
|
||||
platform: flags.enum({
|
||||
platform: Flags.enum({
|
||||
char: 'p',
|
||||
options: ['android', 'ios', 'all'],
|
||||
}),
|
||||
profile: flags.string({
|
||||
profile: Flags.string({
|
||||
description:
|
||||
'Name of the submit profile from eas.json. Defaults to "production" if defined in eas.json.',
|
||||
}),
|
||||
latest: flags.boolean({
|
||||
latest: Flags.boolean({
|
||||
description: 'Submit the latest build for specified platform',
|
||||
exclusive: ['id', 'path', 'url'],
|
||||
}),
|
||||
id: flags.string({
|
||||
id: Flags.string({
|
||||
description: 'ID of the build to submit',
|
||||
exclusive: ['latest, path, url'],
|
||||
}),
|
||||
path: flags.string({
|
||||
path: Flags.string({
|
||||
description: 'Path to the .apk/.aab/.ipa file',
|
||||
exclusive: ['latest', 'id', 'url'],
|
||||
}),
|
||||
url: flags.string({
|
||||
url: Flags.string({
|
||||
description: 'App archive url',
|
||||
exclusive: ['latest', 'id', 'path'],
|
||||
}),
|
||||
verbose: flags.boolean({
|
||||
verbose: Flags.boolean({
|
||||
description: 'Always print logs from Submission Service',
|
||||
default: false,
|
||||
}),
|
||||
wait: flags.boolean({
|
||||
wait: Flags.boolean({
|
||||
description: 'Wait for submission to complete',
|
||||
default: true,
|
||||
allowNo: true,
|
||||
}),
|
||||
'non-interactive': flags.boolean({
|
||||
'non-interactive': Flags.boolean({
|
||||
default: false,
|
||||
description: 'Run command in non-interactive mode',
|
||||
}),
|
||||
};
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { flags: rawFlags } = this.parse(Submit);
|
||||
const { flags: rawFlags } = await this.parse(Submit);
|
||||
const flags = await this.sanitizeFlagsAsync(rawFlags);
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
@@ -135,7 +134,7 @@ See how to configure submits with eas.json: ${link('https://docs.expo.dev/submit
|
||||
}
|
||||
}
|
||||
|
||||
private async sanitizeFlagsAsync(flags: RawFlags): Promise<Flags> {
|
||||
private async sanitizeFlagsAsync(flags: RawCommandFlags): Promise<CommandFlags> {
|
||||
const {
|
||||
platform,
|
||||
verbose,
|
||||
@@ -146,13 +145,13 @@ See how to configure submits with eas.json: ${link('https://docs.expo.dev/submit
|
||||
} = flags;
|
||||
|
||||
if (!flags.platform && nonInteractive) {
|
||||
error('--platform is required when building in non-interactive mode', { exit: 1 });
|
||||
Errors.error('--platform is required when building in non-interactive mode', { exit: 1 });
|
||||
}
|
||||
|
||||
const requestedPlatform = await selectRequestedPlatformAsync(flags.platform);
|
||||
if (requestedPlatform === RequestedPlatform.All) {
|
||||
if (archiveFlags.id || archiveFlags.path || archiveFlags.url) {
|
||||
error(
|
||||
Errors.error(
|
||||
'--id, --path, and --url params are only supported when performing a single-platform submit',
|
||||
{ exit: 1 }
|
||||
);
|
||||
|
||||
@@ -2,26 +2,22 @@ import { ExpoConfig, getConfig, modifyConfigAsync } from '@expo/config';
|
||||
import { Platform, Workflow } from '@expo/eas-build-job';
|
||||
import chalk from 'chalk';
|
||||
|
||||
import { getEASUpdateURL } from '../../api';
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import Log, { learnMore } from '../../log';
|
||||
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
||||
import { resolveWorkflowAsync } from '../../project/workflow';
|
||||
|
||||
const EAS_UPDATE_URL = 'https://u.expo.dev';
|
||||
const DEFAULT_MANAGED_RUNTIME_VERSION = { policy: 'sdkVersion' } as const;
|
||||
const DEFAULT_BARE_RUNTIME_VERSION = '1.0.0';
|
||||
|
||||
export async function getEASUpdateURLAsync(exp: ExpoConfig): Promise<string> {
|
||||
const projectId = await getProjectIdAsync(exp);
|
||||
return new URL(projectId, EAS_UPDATE_URL).href;
|
||||
}
|
||||
|
||||
async function configureProjectForEASUpdateAsync(
|
||||
projectDir: string,
|
||||
exp: ExpoConfig,
|
||||
isBare: boolean
|
||||
): Promise<void> {
|
||||
const easUpdateURL = await getEASUpdateURLAsync(exp);
|
||||
const projectId = await getProjectIdAsync(exp);
|
||||
const easUpdateURL = getEASUpdateURL(projectId);
|
||||
const preexistingRuntimeVersion = exp.runtimeVersion;
|
||||
const defaultRuntimeVersion = isBare
|
||||
? DEFAULT_BARE_RUNTIME_VERSION
|
||||
@@ -63,7 +59,7 @@ async function configureProjectForEASUpdateAsync(
|
||||
);
|
||||
Log.log(
|
||||
chalk.bold(
|
||||
`{\n updates": {\n "url": "${easUpdateURL}"\n },\n "runtimeVersion": {\n "policy": "sdkVersion"\n }\n}`
|
||||
`{\n "updates": {\n "url": "${easUpdateURL}"\n },\n "runtimeVersion": {\n "policy": "sdkVersion"\n }\n}`
|
||||
)
|
||||
);
|
||||
Log.addNewLineIfNone();
|
||||
@@ -77,7 +73,6 @@ async function configureProjectForEASUpdateAsync(
|
||||
}
|
||||
|
||||
export default class UpdateConfigure extends EasCommand {
|
||||
static hidden = true;
|
||||
static description = 'Configure the project to support EAS Update.';
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
} from '../../graphql/generated';
|
||||
import Log from '../../log';
|
||||
import { confirmAsync } from '../../prompts';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
|
||||
async function deleteUpdateGroupAsync({
|
||||
group,
|
||||
@@ -35,7 +36,6 @@ async function deleteUpdateGroupAsync({
|
||||
}
|
||||
|
||||
export default class UpdateDelete extends EasCommand {
|
||||
static hidden = true;
|
||||
static description = 'Delete all the updates in an update Group.';
|
||||
|
||||
static args = [
|
||||
@@ -47,7 +47,7 @@ export default class UpdateDelete extends EasCommand {
|
||||
];
|
||||
|
||||
static flags = {
|
||||
json: flags.boolean({
|
||||
json: Flags.boolean({
|
||||
description: `Return a json with the group ID of the deleted updates.`,
|
||||
default: false,
|
||||
}),
|
||||
@@ -57,9 +57,11 @@ export default class UpdateDelete extends EasCommand {
|
||||
const {
|
||||
args: { groupId: group },
|
||||
flags: { json: jsonFlag },
|
||||
} = this.parse(UpdateDelete);
|
||||
} = await this.parse(UpdateDelete);
|
||||
|
||||
if (!jsonFlag) {
|
||||
if (jsonFlag) {
|
||||
enableJsonOutput();
|
||||
} else {
|
||||
const shouldAbort = await confirmAsync({
|
||||
message:
|
||||
`🚨${chalk.red('CAUTION')}🚨\n\n` +
|
||||
@@ -80,10 +82,9 @@ export default class UpdateDelete extends EasCommand {
|
||||
await deleteUpdateGroupAsync({ group });
|
||||
|
||||
if (jsonFlag) {
|
||||
Log.log(JSON.stringify({ group }));
|
||||
return;
|
||||
printJsonOnlyOutput({ group });
|
||||
} else {
|
||||
Log.withTick(`Deleted update group ${group}`);
|
||||
}
|
||||
|
||||
Log.withTick(`Deleted update group ${group}`);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
import { ExpoConfig, getConfig } from '@expo/config';
|
||||
import { Updates } from '@expo/config-plugins';
|
||||
import { Platform, Workflow } from '@expo/eas-build-job';
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
import assert from 'assert';
|
||||
import chalk from 'chalk';
|
||||
import dateFormat from 'dateformat';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
import { getEASUpdateURL } from '../../api';
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client';
|
||||
import {
|
||||
@@ -16,9 +17,10 @@ import {
|
||||
Update,
|
||||
UpdateInfoGroup,
|
||||
User,
|
||||
ViewBranchQuery,
|
||||
ViewBranchUpdatesQuery,
|
||||
} from '../../graphql/generated';
|
||||
import { PublishMutation } from '../../graphql/mutations/PublishMutation';
|
||||
import { UpdateQuery } from '../../graphql/queries/UpdateQuery';
|
||||
import Log from '../../log';
|
||||
import { ora } from '../../ora';
|
||||
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
||||
@@ -34,12 +36,11 @@ import { promptAsync, selectAsync } from '../../prompts';
|
||||
import { formatUpdate } from '../../update/utils';
|
||||
import uniqBy from '../../utils/expodash/uniqBy';
|
||||
import formatFields from '../../utils/formatFields';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
import { getVcsClient } from '../../vcs';
|
||||
import { createUpdateBranchOnAppAsync } from '../branch/create';
|
||||
import { listBranchesAsync } from '../branch/list';
|
||||
import { viewUpdateBranchAsync } from '../branch/view';
|
||||
import { createUpdateChannelOnAppAsync } from '../channel/create';
|
||||
import { getEASUpdateURLAsync } from './configure';
|
||||
|
||||
export const defaultPublishPlatforms: PublishPlatform[] = ['android', 'ios'];
|
||||
type PlatformFlag = PublishPlatform | 'all';
|
||||
@@ -109,11 +110,11 @@ async function ensureBranchExistsAsync({
|
||||
}): Promise<{
|
||||
id: string;
|
||||
updates: Exclude<
|
||||
Exclude<ViewBranchQuery['app'], null | undefined>['byId']['updateBranchByName'],
|
||||
Exclude<ViewBranchUpdatesQuery['app'], null | undefined>['byId']['updateBranchByName'],
|
||||
null | undefined
|
||||
>['updates'];
|
||||
}> {
|
||||
const { app } = await viewUpdateBranchAsync({
|
||||
const { app } = await UpdateQuery.viewBranchAsync({
|
||||
appId,
|
||||
name: branchName,
|
||||
});
|
||||
@@ -131,46 +132,45 @@ async function ensureBranchExistsAsync({
|
||||
}
|
||||
|
||||
export default class UpdatePublish extends EasCommand {
|
||||
static hidden = true;
|
||||
static description = 'Publish an update group.';
|
||||
|
||||
static flags = {
|
||||
branch: flags.string({
|
||||
branch: Flags.string({
|
||||
description: 'Branch to publish the update group on',
|
||||
required: false,
|
||||
}),
|
||||
message: flags.string({
|
||||
message: Flags.string({
|
||||
description: 'A short message describing the update',
|
||||
required: false,
|
||||
}),
|
||||
republish: flags.boolean({
|
||||
republish: Flags.boolean({
|
||||
description: 'Republish an update group',
|
||||
exclusive: ['input-dir', 'skip-bundler'],
|
||||
}),
|
||||
group: flags.string({
|
||||
group: Flags.string({
|
||||
description: 'Update group to republish',
|
||||
exclusive: ['input-dir', 'skip-bundler'],
|
||||
}),
|
||||
'input-dir': flags.string({
|
||||
'input-dir': Flags.string({
|
||||
description: 'Location of the bundle',
|
||||
default: 'dist',
|
||||
required: false,
|
||||
}),
|
||||
'skip-bundler': flags.boolean({
|
||||
'skip-bundler': Flags.boolean({
|
||||
description: `Skip running Expo CLI to bundle the app before publishing`,
|
||||
default: false,
|
||||
}),
|
||||
platform: flags.enum({
|
||||
platform: Flags.enum({
|
||||
char: 'p',
|
||||
options: [...defaultPublishPlatforms, 'all'],
|
||||
default: 'all',
|
||||
required: false,
|
||||
}),
|
||||
json: flags.boolean({
|
||||
json: Flags.boolean({
|
||||
description: 'Enable JSON output, non-JSON messages will be printed to stderr',
|
||||
default: false,
|
||||
}),
|
||||
auto: flags.boolean({
|
||||
auto: Flags.boolean({
|
||||
description:
|
||||
'Use the current git branch and commit message for the EAS branch and update message',
|
||||
default: false,
|
||||
@@ -188,9 +188,13 @@ export default class UpdatePublish extends EasCommand {
|
||||
group,
|
||||
'input-dir': inputDir,
|
||||
'skip-bundler': skipBundler,
|
||||
platform,
|
||||
},
|
||||
} = this.parse(UpdatePublish);
|
||||
const platformFlag = this.parse(UpdatePublish).flags.platform as PlatformFlag;
|
||||
} = await this.parse(UpdatePublish);
|
||||
if (jsonFlag) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
const platformFlag = platform as PlatformFlag;
|
||||
// If a group was specified, that means we are republishing it.
|
||||
republish = group ? true : republish;
|
||||
|
||||
@@ -357,10 +361,17 @@ export default class UpdatePublish extends EasCommand {
|
||||
|
||||
// build bundle and upload assets for a new publish
|
||||
if (!skipBundler) {
|
||||
await buildBundlesAsync({ projectDir, inputDir });
|
||||
const bundleSpinner = ora().start('Building bundle...');
|
||||
try {
|
||||
await buildBundlesAsync({ projectDir, inputDir });
|
||||
bundleSpinner.succeed('Built bundle!');
|
||||
} catch (e) {
|
||||
bundleSpinner.fail('Failed to build bundle!');
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
const assetSpinner = ora('Uploading assets...').start();
|
||||
const assetSpinner = ora().start('Uploading assets...');
|
||||
try {
|
||||
const platforms = platformFlag === 'all' ? defaultPublishPlatforms : [platformFlag];
|
||||
const assets = await collectAssetsAsync({ inputDir: inputDir!, platforms });
|
||||
@@ -412,7 +423,7 @@ export default class UpdatePublish extends EasCommand {
|
||||
}
|
||||
|
||||
if (jsonFlag) {
|
||||
Log.log(JSON.stringify(newUpdates));
|
||||
printJsonOnlyOutput(newUpdates);
|
||||
} else {
|
||||
if (new Set(newUpdates.map(update => update.group)).size > 1) {
|
||||
Log.addNewLineIfNone();
|
||||
@@ -469,7 +480,7 @@ async function getRuntimeVersionObjectAsync(
|
||||
|
||||
function formatUpdateTitle(
|
||||
update: Exclude<
|
||||
Exclude<ViewBranchQuery['app'], null | undefined>['byId']['updateBranchByName'],
|
||||
Exclude<ViewBranchUpdatesQuery['app'], null | undefined>['byId']['updateBranchByName'],
|
||||
null | undefined
|
||||
>['updates'][number]
|
||||
): string {
|
||||
@@ -497,7 +508,8 @@ function formatUpdateTitle(
|
||||
|
||||
async function checkEASUpdateURLIsSetAsync(exp: ExpoConfig): Promise<void> {
|
||||
const configuredURL = exp.updates?.url;
|
||||
const expectedURL = await getEASUpdateURLAsync(exp);
|
||||
const projectId = await getProjectIdAsync(exp);
|
||||
const expectedURL = getEASUpdateURL(projectId);
|
||||
|
||||
if (configuredURL !== expectedURL) {
|
||||
throw new Error(
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { Flags } from '@oclif/core';
|
||||
import assert from 'assert';
|
||||
import chalk from 'chalk';
|
||||
import CliTable from 'cli-table3';
|
||||
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import { ViewAllUpdatesQuery } from '../../graphql/generated';
|
||||
import { UpdateQuery } from '../../graphql/queries/UpdateQuery';
|
||||
import Log from '../../log';
|
||||
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
||||
import { promptAsync } from '../../prompts';
|
||||
import { FormatUpdateParameter, UPDATE_COLUMNS, formatUpdate } from '../../update/utils';
|
||||
import groupBy from '../../utils/expodash/groupBy';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
import { getVcsClient } from '../../vcs';
|
||||
|
||||
type UpdateGroupDescription = FormatUpdateParameter & {
|
||||
branch: string;
|
||||
group: string;
|
||||
platforms: string;
|
||||
runtimeVersion: string;
|
||||
};
|
||||
|
||||
export default class BranchView extends EasCommand {
|
||||
static description = 'View the recent updates for a branch';
|
||||
|
||||
static flags = {
|
||||
branch: Flags.string({
|
||||
description: 'List all updates on this branch',
|
||||
exclusive: ['all'],
|
||||
}),
|
||||
all: Flags.boolean({
|
||||
description: 'List all updates associated with this project',
|
||||
exclusive: ['branch'],
|
||||
default: false,
|
||||
}),
|
||||
json: Flags.boolean({
|
||||
description: `Return a json with all of the recent update groups.`,
|
||||
default: false,
|
||||
}),
|
||||
};
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const {
|
||||
flags: { branch: branchFlag, all, json: jsonFlag },
|
||||
} = await this.parse(BranchView);
|
||||
if (jsonFlag) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
||||
const projectId = await getProjectIdAsync(exp);
|
||||
|
||||
let updateGroupDescriptions: UpdateGroupDescription[];
|
||||
if (all) {
|
||||
const branchesAndUpdates = await UpdateQuery.viewAllAsync({ appId: projectId });
|
||||
updateGroupDescriptions = getUpdateGroupDescriptions(
|
||||
branchesAndUpdates.app.byId.updateBranches
|
||||
);
|
||||
} else {
|
||||
let branchInteractive: string | undefined;
|
||||
if (!branchFlag) {
|
||||
const validationMessage = 'Branch name may not be empty.';
|
||||
if (jsonFlag) {
|
||||
throw new Error(validationMessage);
|
||||
}
|
||||
({ name: branchInteractive } = await promptAsync({
|
||||
type: 'text',
|
||||
name: 'name',
|
||||
message: 'Please enter the name of the branch whose updates you wish to view:',
|
||||
initial: (await getVcsClient().getBranchNameAsync()) ?? undefined,
|
||||
validate: (value: any) => (value ? true : validationMessage),
|
||||
}));
|
||||
}
|
||||
const branch = branchFlag ?? branchInteractive;
|
||||
assert(branch, 'Branch name may not be empty.');
|
||||
|
||||
const branchesAndUpdates = await UpdateQuery.viewBranchAsync({
|
||||
appId: projectId,
|
||||
name: branch,
|
||||
});
|
||||
const UpdateBranch = branchesAndUpdates.app?.byId.updateBranchByName;
|
||||
if (!UpdateBranch) {
|
||||
throw new Error(`Could not find branch "${branch}"`);
|
||||
}
|
||||
updateGroupDescriptions = getUpdateGroupDescriptions([UpdateBranch]);
|
||||
}
|
||||
|
||||
if (jsonFlag) {
|
||||
printJsonOnlyOutput(updateGroupDescriptions);
|
||||
} else {
|
||||
logAsTable(updateGroupDescriptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getUpdateGroupDescriptions(
|
||||
branchesAndUpdates: ViewAllUpdatesQuery['app']['byId']['updateBranches']
|
||||
): UpdateGroupDescription[] {
|
||||
const flattenedBranchesAndUpdates = branchesAndUpdates.flatMap(branch =>
|
||||
branch.updates.map(update => {
|
||||
return { branch: branch.name, ...update };
|
||||
})
|
||||
);
|
||||
const updateGroupDescriptions = Object.values(
|
||||
groupBy(flattenedBranchesAndUpdates, update => update.group)
|
||||
).map(updateGroup => {
|
||||
const platforms = updateGroup
|
||||
.map(update => update.platform)
|
||||
.sort()
|
||||
.join(', ');
|
||||
return { ...updateGroup[0], platforms };
|
||||
});
|
||||
updateGroupDescriptions.sort(
|
||||
(a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
|
||||
);
|
||||
return updateGroupDescriptions;
|
||||
}
|
||||
|
||||
function logAsTable(updateGroupDescriptions: UpdateGroupDescription[]): void {
|
||||
const table = new CliTable({
|
||||
head: ['Branch', ...UPDATE_COLUMNS],
|
||||
wordWrap: true,
|
||||
});
|
||||
table.push(
|
||||
...updateGroupDescriptions.map(updateGroupDescription => [
|
||||
updateGroupDescription.branch,
|
||||
formatUpdate(updateGroupDescription),
|
||||
updateGroupDescription.runtimeVersion,
|
||||
updateGroupDescription.group,
|
||||
updateGroupDescription.platforms,
|
||||
])
|
||||
);
|
||||
Log.addNewLineIfNone();
|
||||
Log.log(chalk.bold('Recently published update groups:'));
|
||||
Log.log(table.toString());
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
import Table from 'cli-table3';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
@@ -7,6 +7,7 @@ import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client';
|
||||
import { UpdatesByGroupQuery, UpdatesByGroupQueryVariables } from '../../graphql/generated';
|
||||
import Log from '../../log';
|
||||
import { UPDATE_COLUMNS, formatUpdate, getPlatformsForGroup } from '../../update/utils';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
|
||||
export async function viewUpdateAsync({
|
||||
groupId,
|
||||
@@ -50,7 +51,6 @@ export async function viewUpdateAsync({
|
||||
return data;
|
||||
}
|
||||
export default class UpdateView extends EasCommand {
|
||||
static hidden = true;
|
||||
static description = 'Update group details.';
|
||||
|
||||
static args = [
|
||||
@@ -62,7 +62,7 @@ export default class UpdateView extends EasCommand {
|
||||
];
|
||||
|
||||
static flags = {
|
||||
json: flags.boolean({
|
||||
json: Flags.boolean({
|
||||
description: `Return a json with the updates belonging to the group.`,
|
||||
default: false,
|
||||
}),
|
||||
@@ -72,31 +72,33 @@ export default class UpdateView extends EasCommand {
|
||||
const {
|
||||
args: { groupId },
|
||||
flags: { json: jsonFlag },
|
||||
} = this.parse(UpdateView);
|
||||
} = await this.parse(UpdateView);
|
||||
if (jsonFlag) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
|
||||
const { updatesByGroup } = await viewUpdateAsync({ groupId });
|
||||
|
||||
if (jsonFlag) {
|
||||
Log.log(JSON.stringify(updatesByGroup));
|
||||
return;
|
||||
printJsonOnlyOutput(updatesByGroup);
|
||||
} else {
|
||||
const groupTable = new Table({
|
||||
head: [...UPDATE_COLUMNS],
|
||||
wordWrap: true,
|
||||
});
|
||||
|
||||
const representativeUpdate = updatesByGroup[0];
|
||||
groupTable.push([
|
||||
formatUpdate(representativeUpdate),
|
||||
representativeUpdate.runtimeVersion,
|
||||
representativeUpdate.group,
|
||||
getPlatformsForGroup({
|
||||
updates: updatesByGroup,
|
||||
group: updatesByGroup[0]?.group,
|
||||
}),
|
||||
]);
|
||||
|
||||
Log.log(groupTable.toString());
|
||||
}
|
||||
|
||||
const groupTable = new Table({
|
||||
head: [...UPDATE_COLUMNS],
|
||||
wordWrap: true,
|
||||
});
|
||||
|
||||
const representativeUpdate = updatesByGroup[0];
|
||||
groupTable.push([
|
||||
formatUpdate(representativeUpdate),
|
||||
representativeUpdate.runtimeVersion,
|
||||
representativeUpdate.group,
|
||||
getPlatformsForGroup({
|
||||
updates: updatesByGroup,
|
||||
group: updatesByGroup[0]?.group,
|
||||
}),
|
||||
]);
|
||||
|
||||
Log.log(groupTable.toString());
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import { WebhookType } from '../../graphql/generated';
|
||||
@@ -12,21 +12,21 @@ export default class WebhookCreate extends EasCommand {
|
||||
static description = 'Create a webhook on the current project.';
|
||||
|
||||
static flags = {
|
||||
event: flags.enum({
|
||||
event: Flags.enum({
|
||||
description: 'Event type that triggers the webhook',
|
||||
options: [WebhookType.Build, WebhookType.Submit],
|
||||
}),
|
||||
url: flags.string({
|
||||
url: Flags.string({
|
||||
description: 'Webhook URL',
|
||||
}),
|
||||
secret: flags.string({
|
||||
secret: Flags.string({
|
||||
description:
|
||||
"Secret used to create a hash signature of the request payload, provided in the 'Expo-Signature' header.",
|
||||
}),
|
||||
};
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { flags } = this.parse(WebhookCreate);
|
||||
const { flags } = await this.parse(WebhookCreate);
|
||||
const webhookInputParams = await prepareInputParamsAsync(flags);
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
|
||||
@@ -27,7 +27,7 @@ export default class WebhookDelete extends EasCommand {
|
||||
async runAsync(): Promise<void> {
|
||||
let {
|
||||
args: { ID: webhookId },
|
||||
} = this.parse(WebhookDelete);
|
||||
} = await this.parse(WebhookDelete);
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getConfig } from '@expo/config';
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
@@ -18,7 +18,7 @@ export default class WebhookList extends EasCommand {
|
||||
static description = 'List webhooks on the current project.';
|
||||
|
||||
static flags = {
|
||||
event: flags.enum({
|
||||
event: Flags.enum({
|
||||
description: 'Event type that triggers the webhook',
|
||||
options: [WebhookType.Build, WebhookType.Submit],
|
||||
}),
|
||||
@@ -27,7 +27,7 @@ export default class WebhookList extends EasCommand {
|
||||
async runAsync(): Promise<void> {
|
||||
const {
|
||||
flags: { event },
|
||||
} = this.parse(WebhookList);
|
||||
} = await this.parse(WebhookList);
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { flags } from '@oclif/command';
|
||||
import { Flags } from '@oclif/core';
|
||||
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import { WebhookType } from '../../graphql/generated';
|
||||
@@ -12,25 +12,25 @@ export default class WebhookUpdate extends EasCommand {
|
||||
static description = 'Create a webhook on the current project.';
|
||||
|
||||
static flags = {
|
||||
id: flags.string({
|
||||
id: Flags.string({
|
||||
description: 'Webhook ID',
|
||||
required: true,
|
||||
}),
|
||||
event: flags.enum({
|
||||
event: Flags.enum({
|
||||
description: 'Event type that triggers the webhook',
|
||||
options: [WebhookType.Build, WebhookType.Submit],
|
||||
}),
|
||||
url: flags.string({
|
||||
url: Flags.string({
|
||||
description: 'Webhook URL',
|
||||
}),
|
||||
secret: flags.string({
|
||||
secret: Flags.string({
|
||||
description:
|
||||
"Secret used to create a hash signature of the request payload, provided in the 'Expo-Signature' header.",
|
||||
}),
|
||||
};
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { flags } = this.parse(WebhookUpdate);
|
||||
const { flags } = await this.parse(WebhookUpdate);
|
||||
|
||||
const webhookId = flags.id;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ export default class WebhookView extends EasCommand {
|
||||
async runAsync(): Promise<void> {
|
||||
const {
|
||||
args: { ID: webhookId },
|
||||
} = this.parse(WebhookView);
|
||||
} = await this.parse(WebhookView);
|
||||
|
||||
const spinner = ora(`Fetching the webhook details for ID ${webhookId}`).start();
|
||||
try {
|
||||
|
||||
+1
-5
@@ -1,4 +1,4 @@
|
||||
import { BundleIdCapability, CapabilityType } from '@expo/apple-utils';
|
||||
import { BundleIdCapability } from '@expo/apple-utils';
|
||||
|
||||
import {
|
||||
CapabilityMapping,
|
||||
@@ -222,10 +222,6 @@ describe(syncCapabilitiesForEntitlementsAsync, () => {
|
||||
const bundleId = {
|
||||
getBundleIdCapabilitiesAsync: jest.fn(() => [
|
||||
new BundleIdCapability({}, 'XXX_IN_APP_PURCHASE', { settings: null }),
|
||||
new BundleIdCapability({}, 'FOOBAR', {
|
||||
settings: null,
|
||||
capabilityType: CapabilityType.PUSH_NOTIFICATIONS,
|
||||
}),
|
||||
new BundleIdCapability({}, 'XXX_GAME_CENTER', { settings: null }),
|
||||
]),
|
||||
updateBundleIdCapabilityAsync: jest.fn(),
|
||||
|
||||
@@ -214,11 +214,9 @@ function getCapabilitiesToDisable(
|
||||
// might be enabling capabilities in modifiers.
|
||||
|
||||
for (const existingCapability of currentCapabilities) {
|
||||
// Special case APNS because it's always enabled in Expo,
|
||||
// GC and IAP are always enabled in apps by default so we should avoid modifying them.
|
||||
if (
|
||||
existingCapability.isType(CapabilityType.IN_APP_PURCHASE) ||
|
||||
existingCapability.isType(CapabilityType.PUSH_NOTIFICATIONS) ||
|
||||
existingCapability.isType(CapabilityType.GAME_CENTER)
|
||||
) {
|
||||
continue;
|
||||
|
||||
@@ -67,7 +67,11 @@ export async function ensureBundleIdExistsWithNameAsync(
|
||||
spinner.fail(`Failed to register bundle identifier ${chalk.dim(bundleIdentifier)}`);
|
||||
|
||||
// Assert contract errors for easier resolution when the user has an expired developer account.
|
||||
if (err.message.match(/forbidden for security reasons/)) {
|
||||
if (
|
||||
err.message.match(/forbidden for security reasons/) ||
|
||||
// Unable to process request - PLA Update available - You currently don't have access to this membership resource. To resolve this issue, agree to the latest Program License Agreement in your developer account.
|
||||
err.message.match(/agree/)
|
||||
) {
|
||||
await assertContractMessagesAsync(context);
|
||||
}
|
||||
}
|
||||
|
||||
+102
-33
@@ -3719,39 +3719,6 @@ export type EditUpdateBranchMutation = (
|
||||
) }
|
||||
);
|
||||
|
||||
export type ViewBranchQueryVariables = Exact<{
|
||||
appId: Scalars['String'];
|
||||
name: Scalars['String'];
|
||||
limit: Scalars['Int'];
|
||||
}>;
|
||||
|
||||
|
||||
export type ViewBranchQuery = (
|
||||
{ __typename?: 'RootQuery' }
|
||||
& { app: (
|
||||
{ __typename?: 'AppQuery' }
|
||||
& { byId: (
|
||||
{ __typename?: 'App' }
|
||||
& Pick<App, 'id'>
|
||||
& { updateBranchByName?: Maybe<(
|
||||
{ __typename?: 'UpdateBranch' }
|
||||
& Pick<UpdateBranch, 'id' | 'name'>
|
||||
& { updates: Array<(
|
||||
{ __typename?: 'Update' }
|
||||
& Pick<Update, 'id' | 'group' | 'message' | 'createdAt' | 'runtimeVersion' | 'platform' | 'manifestFragment'>
|
||||
& { actor?: Maybe<(
|
||||
{ __typename?: 'User' }
|
||||
& Pick<User, 'username' | 'id'>
|
||||
) | (
|
||||
{ __typename?: 'Robot' }
|
||||
& Pick<Robot, 'firstName' | 'id'>
|
||||
)> }
|
||||
)> }
|
||||
)> }
|
||||
) }
|
||||
) }
|
||||
);
|
||||
|
||||
export type CancelBuildMutationVariables = Exact<{
|
||||
buildId: Scalars['ID'];
|
||||
}>;
|
||||
@@ -3786,6 +3753,43 @@ export type CreateUpdateChannelOnAppMutation = (
|
||||
) }
|
||||
);
|
||||
|
||||
export type GetChannelInfoQueryVariables = Exact<{
|
||||
appId: Scalars['String'];
|
||||
name: Scalars['String'];
|
||||
}>;
|
||||
|
||||
|
||||
export type GetChannelInfoQuery = (
|
||||
{ __typename?: 'RootQuery' }
|
||||
& { app: (
|
||||
{ __typename?: 'AppQuery' }
|
||||
& { byId: (
|
||||
{ __typename?: 'App' }
|
||||
& Pick<App, 'id'>
|
||||
& { updateChannelByName?: Maybe<(
|
||||
{ __typename?: 'UpdateChannel' }
|
||||
& Pick<UpdateChannel, 'id' | 'name'>
|
||||
)> }
|
||||
) }
|
||||
) }
|
||||
);
|
||||
|
||||
export type DeleteUpdateChannelMutationVariables = Exact<{
|
||||
channelId: Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type DeleteUpdateChannelMutation = (
|
||||
{ __typename?: 'RootMutation' }
|
||||
& { updateChannel: (
|
||||
{ __typename?: 'UpdateChannelMutation' }
|
||||
& { deleteUpdateChannel: (
|
||||
{ __typename?: 'DeleteUpdateChannelResult' }
|
||||
& Pick<DeleteUpdateChannelResult, 'id'>
|
||||
) }
|
||||
) }
|
||||
);
|
||||
|
||||
export type GetChannelByNameToEditQueryVariables = Exact<{
|
||||
appId: Scalars['String'];
|
||||
channelName: Scalars['String'];
|
||||
@@ -5367,6 +5371,71 @@ export type GetAllSubmissionsForAppQuery = (
|
||||
) }
|
||||
);
|
||||
|
||||
export type ViewAllUpdatesQueryVariables = Exact<{
|
||||
appId: Scalars['String'];
|
||||
limit: Scalars['Int'];
|
||||
}>;
|
||||
|
||||
|
||||
export type ViewAllUpdatesQuery = (
|
||||
{ __typename?: 'RootQuery' }
|
||||
& { app: (
|
||||
{ __typename?: 'AppQuery' }
|
||||
& { byId: (
|
||||
{ __typename?: 'App' }
|
||||
& Pick<App, 'id'>
|
||||
& { updateBranches: Array<(
|
||||
{ __typename?: 'UpdateBranch' }
|
||||
& Pick<UpdateBranch, 'id' | 'name'>
|
||||
& { updates: Array<(
|
||||
{ __typename?: 'Update' }
|
||||
& Pick<Update, 'id' | 'group' | 'message' | 'createdAt' | 'runtimeVersion' | 'platform'>
|
||||
& { actor?: Maybe<(
|
||||
{ __typename?: 'User' }
|
||||
& Pick<User, 'username' | 'id'>
|
||||
) | (
|
||||
{ __typename?: 'Robot' }
|
||||
& Pick<Robot, 'firstName' | 'id'>
|
||||
)> }
|
||||
)> }
|
||||
)> }
|
||||
) }
|
||||
) }
|
||||
);
|
||||
|
||||
export type ViewBranchUpdatesQueryVariables = Exact<{
|
||||
appId: Scalars['String'];
|
||||
name: Scalars['String'];
|
||||
limit: Scalars['Int'];
|
||||
}>;
|
||||
|
||||
|
||||
export type ViewBranchUpdatesQuery = (
|
||||
{ __typename?: 'RootQuery' }
|
||||
& { app: (
|
||||
{ __typename?: 'AppQuery' }
|
||||
& { byId: (
|
||||
{ __typename?: 'App' }
|
||||
& Pick<App, 'id'>
|
||||
& { updateBranchByName?: Maybe<(
|
||||
{ __typename?: 'UpdateBranch' }
|
||||
& Pick<UpdateBranch, 'id' | 'name'>
|
||||
& { updates: Array<(
|
||||
{ __typename?: 'Update' }
|
||||
& Pick<Update, 'id' | 'group' | 'message' | 'createdAt' | 'runtimeVersion' | 'platform' | 'manifestFragment'>
|
||||
& { actor?: Maybe<(
|
||||
{ __typename?: 'User' }
|
||||
& Pick<User, 'username' | 'id'>
|
||||
) | (
|
||||
{ __typename?: 'Robot' }
|
||||
& Pick<Robot, 'firstName' | 'id'>
|
||||
)> }
|
||||
)> }
|
||||
)> }
|
||||
) }
|
||||
) }
|
||||
);
|
||||
|
||||
export type CurrentUserQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
import { graphqlClient, withErrorHandlingAsync } from '../client';
|
||||
import {
|
||||
ViewAllUpdatesQuery,
|
||||
ViewAllUpdatesQueryVariables,
|
||||
ViewBranchUpdatesQuery,
|
||||
ViewBranchUpdatesQueryVariables,
|
||||
} from '../generated';
|
||||
|
||||
const PAGE_LIMIT = 10_000;
|
||||
|
||||
export const UpdateQuery = {
|
||||
async viewAllAsync({ appId }: { appId: string }): Promise<ViewAllUpdatesQuery> {
|
||||
return withErrorHandlingAsync(
|
||||
graphqlClient
|
||||
.query<ViewAllUpdatesQuery, ViewAllUpdatesQueryVariables>(
|
||||
gql`
|
||||
query ViewAllUpdates($appId: String!, $limit: Int!) {
|
||||
app {
|
||||
byId(appId: $appId) {
|
||||
id
|
||||
updateBranches(offset: 0, limit: $limit) {
|
||||
id
|
||||
name
|
||||
updates(offset: 0, limit: $limit) {
|
||||
id
|
||||
group
|
||||
message
|
||||
createdAt
|
||||
runtimeVersion
|
||||
platform
|
||||
actor {
|
||||
id
|
||||
... on User {
|
||||
username
|
||||
}
|
||||
... on Robot {
|
||||
firstName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
{
|
||||
appId,
|
||||
limit: PAGE_LIMIT,
|
||||
},
|
||||
{ additionalTypenames: ['UpdateBranch', 'Update'] }
|
||||
)
|
||||
.toPromise()
|
||||
);
|
||||
},
|
||||
async viewBranchAsync({ appId, name }: Pick<ViewBranchUpdatesQueryVariables, 'appId' | 'name'>) {
|
||||
return withErrorHandlingAsync<ViewBranchUpdatesQuery>(
|
||||
graphqlClient
|
||||
.query<ViewBranchUpdatesQuery, ViewBranchUpdatesQueryVariables>(
|
||||
gql`
|
||||
query ViewBranchUpdates($appId: String!, $name: String!, $limit: Int!) {
|
||||
app {
|
||||
byId(appId: $appId) {
|
||||
id
|
||||
updateBranchByName(name: $name) {
|
||||
id
|
||||
name
|
||||
updates(offset: 0, limit: $limit) {
|
||||
id
|
||||
group
|
||||
message
|
||||
createdAt
|
||||
runtimeVersion
|
||||
platform
|
||||
manifestFragment
|
||||
actor {
|
||||
id
|
||||
... on User {
|
||||
username
|
||||
}
|
||||
... on Robot {
|
||||
firstName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
{
|
||||
appId,
|
||||
name,
|
||||
limit: PAGE_LIMIT,
|
||||
},
|
||||
{ additionalTypenames: ['UpdateBranch', 'Update'] }
|
||||
)
|
||||
.toPromise()
|
||||
);
|
||||
},
|
||||
};
|
||||
@@ -1 +1 @@
|
||||
export { run } from '@oclif/command';
|
||||
export { run } from '@oclif/core';
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Platform, Workflow } from '@expo/eas-build-job';
|
||||
import { exit } from '@oclif/errors';
|
||||
import { Errors } from '@oclif/core';
|
||||
import assert from 'assert';
|
||||
import semver from 'semver';
|
||||
|
||||
@@ -30,6 +30,6 @@ export async function checkExpoSdkIsSupportedAsync(ctx: BuildContext<Platform>):
|
||||
message: `${unsupportedSdkMessage} Do you want to proceed?`,
|
||||
});
|
||||
if (!proceed) {
|
||||
exit(1);
|
||||
Errors.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Platform } from '@expo/eas-build-job';
|
||||
import { exit } from '@oclif/errors';
|
||||
import { Errors } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
import type MetroConfig from 'metro-config';
|
||||
import resolveFrom from 'resolve-from';
|
||||
@@ -49,7 +49,7 @@ export async function validateMetroConfigForManagedWorkflowAsync(
|
||||
});
|
||||
if (shouldAbort) {
|
||||
Log.error('Aborting...');
|
||||
exit(1);
|
||||
Errors.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import { AssetMetadataStatus, PartialManifestAsset } from '../graphql/generated'
|
||||
import { PublishMutation } from '../graphql/mutations/PublishMutation';
|
||||
import { PresignedPost } from '../graphql/mutations/UploadSessionMutation';
|
||||
import { PublishQuery } from '../graphql/queries/PublishQuery';
|
||||
import Log from '../log';
|
||||
import { uploadWithPresignedPostAsync } from '../uploads';
|
||||
import { expoCommandAsync } from '../utils/expoCli';
|
||||
import uniqBy from '../utils/expodash/uniqBy';
|
||||
@@ -157,8 +156,11 @@ export async function buildBundlesAsync({
|
||||
throw new Error('Could not locate package.json');
|
||||
}
|
||||
|
||||
Log.withTick(`Building bundle with expo-cli...`);
|
||||
await expoCommandAsync(projectDir, ['export', '--output-dir', inputDir, '--experimental-bundle']);
|
||||
await expoCommandAsync(
|
||||
projectDir,
|
||||
['export', '--output-dir', inputDir, '--experimental-bundle'],
|
||||
{ silent: true }
|
||||
);
|
||||
}
|
||||
|
||||
export async function resolveInputDirectoryAsync(customInputDirectory: string): Promise<string> {
|
||||
|
||||
@@ -174,7 +174,14 @@ export default class IosSubmitCommand {
|
||||
|
||||
// interpret this to mean the user had some intention of passing in ASC Api key
|
||||
if (ascApiKeyPath || ascApiKeyIssuerId || ascApiKeyId) {
|
||||
Log.warn(`ascApiKeyPath, ascApiKeyIssuerId and ascApiKeyId must all be defined in eas.json`);
|
||||
const message = `ascApiKeyPath, ascApiKeyIssuerId and ascApiKeyId must all be defined in eas.json`;
|
||||
|
||||
// in non-interactive mode, we should fail
|
||||
if (this.ctx.nonInteractive) {
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
Log.warn(message);
|
||||
return result({
|
||||
sourceType: AscApiKeySourceType.prompt,
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { error } from '@oclif/errors';
|
||||
import { Errors } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
import nullthrows from 'nullthrows';
|
||||
|
||||
@@ -13,7 +13,7 @@ export async function showLoginPromptAsync({
|
||||
printNewLine = false,
|
||||
} = {}): Promise<void> {
|
||||
if (nonInteractive) {
|
||||
error(
|
||||
Errors.error(
|
||||
`Either log in with ${chalk.bold('eas login')} or set the ${chalk.bold(
|
||||
'EXPO_TOKEN'
|
||||
)} environment variable if you're using EAS CLI on CI (${learnMore(
|
||||
|
||||
@@ -4,7 +4,11 @@ import resolveFrom from 'resolve-from';
|
||||
|
||||
import Log from '../log';
|
||||
|
||||
export async function expoCommandAsync(projectDir: string, args: string[]): Promise<void> {
|
||||
export async function expoCommandAsync(
|
||||
projectDir: string,
|
||||
args: string[],
|
||||
{ silent = false }: { silent?: boolean } = {}
|
||||
): Promise<void> {
|
||||
const expoCliPath = resolveFrom(projectDir, 'expo/bin/cli.js');
|
||||
const spawnPromise = spawnAsync(expoCliPath, args, {
|
||||
stdio: ['inherit', 'pipe', 'pipe'], // inherit stdin so user can install a missing expo-cli from inside this command
|
||||
@@ -15,15 +19,17 @@ export async function expoCommandAsync(projectDir: string, args: string[]): Prom
|
||||
if (!(stdout && stderr)) {
|
||||
throw new Error('Failed to spawn expo-cli');
|
||||
}
|
||||
stdout.on('data', data => {
|
||||
for (const line of data.toString().trim().split('\n')) {
|
||||
Log.log(`${chalk.gray('[expo-cli]')} ${line}`);
|
||||
}
|
||||
});
|
||||
stderr.on('data', data => {
|
||||
for (const line of data.toString().trim().split('\n')) {
|
||||
Log.warn(`${chalk.gray('[expo-cli]')} ${line}`);
|
||||
}
|
||||
});
|
||||
if (!silent) {
|
||||
stdout.on('data', data => {
|
||||
for (const line of data.toString().trim().split('\n')) {
|
||||
Log.log(`${chalk.gray('[expo-cli]')} ${line}`);
|
||||
}
|
||||
});
|
||||
stderr.on('data', data => {
|
||||
for (const line of data.toString().trim().split('\n')) {
|
||||
Log.warn(`${chalk.gray('[expo-cli]')} ${line}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
await spawnPromise;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import spawnAsync from '@expo/spawn-async';
|
||||
import { exit } from '@oclif/errors';
|
||||
import { Errors } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
|
||||
import Log, { learnMore } from '../../log';
|
||||
@@ -23,7 +23,7 @@ export default class GitClient extends Client {
|
||||
)} to use EAS CLI without Git (or any other version control system).`
|
||||
);
|
||||
Log.error(learnMore('https://expo.fyi/eas-vcs-workflow'));
|
||||
exit(1);
|
||||
Errors.exit(1);
|
||||
}
|
||||
|
||||
if (await doesGitRepoExistAsync()) {
|
||||
|
||||
@@ -44,7 +44,11 @@ export class Ignore {
|
||||
return;
|
||||
}
|
||||
const ignoreFilePaths = (
|
||||
await fg(`**/${GITIGNORE_FILENAME}`, { cwd: this.rootDir, ignore: ['node_modules'] })
|
||||
await fg(`**/${GITIGNORE_FILENAME}`, {
|
||||
cwd: this.rootDir,
|
||||
ignore: ['node_modules'],
|
||||
followSymbolicLinks: false,
|
||||
})
|
||||
)
|
||||
// ensure that parent dir is before child directories
|
||||
.sort((a, b) => a.length - b.length && a.localeCompare(b));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@expo/eas-json",
|
||||
"description": "A library for interacting with eas.json",
|
||||
"version": "0.41.0",
|
||||
"version": "0.44.0",
|
||||
"author": "Expo <[email protected]>",
|
||||
"bugs": "https://github.com/expo/eas-cli/issues",
|
||||
"dependencies": {
|
||||
|
||||
File renamed without changes.
Reference in new issue
Block a user