Compare commits

..
Author SHA1 Message Date
Quinlan Jung 377c7a9ebb update CHANGELOG.md 2024-01-18 04:04:34 +00:00
Quinlan Jung ef3edcc787 [eas-cli] prompt user to map channel on update if unmapped 2024-01-17 19:50:02 -08:00
102 changed files with 779 additions and 2163 deletions

No files matched your search

+1 -7
View File
@@ -152,13 +152,7 @@ jobs:
VERSION=$(cat lerna.json | jq -r .version)
echo //registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN > ~/.npmrc
npm dist-tag add eas-cli@$VERSION latest-eas-build-staging
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
- name: Add latest-eas-build tag
run: |
VERSION=$(cat lerna.json | jq -r .version)
echo //registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN > ~/.npmrc
npm dist-tag add eas-cli@$VERSION latest-eas-build
echo "Run \"npm dist-tag add eas-cli@$VERSION latest-eas-build\" to promote it to production."
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
release-changelog:
@@ -1,81 +0,0 @@
name: Open a PR bumping eas-build modules
on: workflow_dispatch
jobs:
open-pr:
name: Open a PR bumping eas-build modules
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: main
token: ${{ secrets.EXPO_BOT_PAT }}
- name: Setup node
uses: actions/setup-node@v2
with:
node-version: 20
- run: yarn install --frozen-lockfile
- name: Configure git
run: |
git config --global user.email "[email protected]"
git config --global user.name "Expo Bot"
- name: Upgrade eas-build modules
run: |
for DIR in packages/eas-cli packages/eas-json; do
pushd $DIR >/dev/null 2>&1
# packages are ordered according to output of `lerna list --toposort`
# https://github.com/expo/turtle-v2/pull/568
for PACKAGE in "@expo/downloader" "@expo/eas-build-job" "@expo/logger" "@expo/template-file" "@expo/steps" "@expo/turtle-spawn" "@expo/build-tools"; do
if grep -q $PACKAGE package.json; then
echo "[$DIR] yarn --exact add $PACKAGE"
yarn add --exact $PACKAGE
fi
done
popd >/dev/null 2>&1
done
- name: Set a branch name
id: bump-branch-name
run: |
HASH="$(echo $RANDOM | md5sum | head -c 10)"
BRANCH_NAME="@expo-bot/eas-build-bump-$HASH"
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_OUTPUT
- name: Create a branch, commit, and push
run: |
BRANCH_NAME="${{ steps.bump-branch-name.outputs.BRANCH_NAME }}"
git checkout -b $BRANCH_NAME
git add .
git commit -m "Upgrade eas-build dependencies"
git push origin $BRANCH_NAME
- name: Open a PR to main
uses: repo-sync/pull-request@v2
id: open-pr
with:
source_branch: '${{ steps.bump-branch-name.outputs.BRANCH_NAME }}'
destination_branch: 'main'
pr_title: 'Upgrade eas-build dependencies'
pr_body: ':arrow_up: Upgrades [`eas-build`](https://github.com/expo/eas-build) dependencies.'
pr_reviewer: 'szdziedzic,radoslawkrzemien,sjchmiela,khamilowicz'
github_token: ${{ secrets.EXPO_BOT_PAT }}
- uses: actions/github-script@v3
with:
github-token: ${{ secrets.EXPO_BOT_PAT }}
script: |
github.issues.createComment({
issue_number: ${{ steps.open-pr.outputs.pr_number }},
owner: context.repo.owner,
repo: context.repo.repo,
body: "/changelog-entry chore Upgrade [`eas-build`](https://github.com/expo/eas-build) dependencies."
})
-10
View File
@@ -1,10 +0,0 @@
{
"eslint.enable": true,
"search.exclude": {
"**/node_modules": true,
"**/bower_components": true,
"**/*.code-search": true,
"**/src/**/build/**": false,
"**/src/build/**": false,
}
}
+3 -139
View File
@@ -8,153 +8,17 @@ This is the log of notable changes to EAS CLI and related packages.
### 🎉 New features
### 🐛 Bug fixes
### 🧹 Chores
- Upgrade [`eas-build`](https://github.com/expo/eas-build) dependencies. ([#2301](https://github.com/expo/eas-cli/pull/2301) by [@expo-bot](https://github.com/expo-bot))
## [7.6.1](https://github.com/expo/eas-cli/releases/tag/v7.6.1) - 2024-03-25
### 🧹 Chores
- Upgrade [`eas-build`](https://github.com/expo/eas-build) dependencies. ([#2291](https://github.com/expo/eas-cli/pull/2291) by [@expo-bot](https://github.com/expo-bot))
- Fix asset limit punctuation. ([#2296](https://github.com/expo/eas-cli/pull/2296) by [@quinlanj](https://github.com/quinlanj))
- Upgrade [`eas-build`](https://github.com/expo/eas-build) dependencies. ([#2293](https://github.com/expo/eas-cli/pull/2293) by [@expo-bot](https://github.com/expo-bot))
## [7.6.0](https://github.com/expo/eas-cli/releases/tag/v7.6.0) - 2024-03-18
### 🎉 New features
- Print uncommitted files in non-interactive mode if they fail the execution. ([#2288](https://github.com/expo/eas-cli/pull/2288) by [@sjchmiela](https://github.com/sjchmiela))
### 🐛 Bug fixes
- Use a custom build config path with POSIX separator when sending data to the EAS Build server. ([#2285](https://github.com/expo/eas-cli/pull/2285) by [@szdziedzic](https://github.com/szdziedzic))
- Improve resolving vcsClient as a part of the project context. ([#2295](https://github.com/expo/eas-cli/pull/2295) by [@szdziedzic](https://github.com/szdziedzic))
### 🧹 Chores
- Upgrade [`eas-build`](https://github.com/expo/eas-build) dependencies. ([#2277](https://github.com/expo/eas-cli/pull/2277) by [@expo-bot](https://github.com/expo-bot))
- Upgrade [`eas-build`](https://github.com/expo/eas-build) dependencies. ([#2283](https://github.com/expo/eas-cli/pull/2283) by [@expo-bot](https://github.com/expo-bot))
- Bump the `@expo/apple-utils` version to switch between the `developer.apple.com` and `developer-mdn.apple.com` domains when one of them doesn't work. ([#2290](https://github.com/expo/eas-cli/pull/2290) by [@szdziedzic](https://github.com/szdziedzic))
## [7.5.0](https://github.com/expo/eas-cli/releases/tag/v7.5.0) - 2024-03-11
### 🎉 New features
- Add `--auto-submit` option to `eas build:internal` command. ([#2271](https://github.com/expo/eas-cli/pull/2271) by [@szdziedzic](https://github.com/szdziedzic))
### 🧹 Chores
- Upgrade [`eas-build`](https://github.com/expo/eas-build) dependencies. ([#2274](https://github.com/expo/eas-cli/pull/2274) by [@expo-bot](https://github.com/expo-bot))
## [7.4.0](https://github.com/expo/eas-cli/releases/tag/v7.4.0) - 2024-03-10
### 🎉 New features
- Use new expo-updates configuration:syncnative for versioned native sync. ([#2269](https://github.com/expo/eas-cli/pull/2269) by [@wschurman](https://github.com/wschurman))
### 🐛 Bug fixes
- Fix expo-updates package version detection for canaries. ([#2243](https://github.com/expo/eas-cli/pull/2243) by [@wschurman](https://github.com/wschurman))
- Add missing `config` property to `eas.json` schema. ([#2248](https://github.com/expo/eas-cli/pull/2248) by [@sjchmiela](https://github.com/sjchmiela))
- Use expo-updates runtime version CLI to generate runtime versions. ([#2251](https://github.com/expo/eas-cli/pull/2251) by [@wschurman](https://github.com/wschurman))
- Update @expo/apple-utils to handle changes in API. ([73ba19de6662763cc6bff9fac6b7700ffbd0e88a](https://github.com/expo/eas-cli/commit/73ba19de6662763cc6bff9fac6b7700ffbd0e88a) by [@brentvatne](https://github.com/brentvatne))
### 🧹 Chores
- Upgrade [`eas-build`](https://github.com/expo/eas-build) dependencies. ([#2237](https://github.com/expo/eas-cli/pull/2237) by [@expo-bot](https://github.com/expo-bot))
- Upgrade [`eas-build`](https://github.com/expo/eas-build) dependencies. ([#2240](https://github.com/expo/eas-cli/pull/2240) by [@expo-bot](https://github.com/expo-bot))
- Upgrade [`eas-build`](https://github.com/expo/eas-build) dependencies. ([#2253](https://github.com/expo/eas-cli/pull/2253) by [@expo-bot](https://github.com/expo-bot))
- Include src/**/build directories in vscode search and replace. ([#2250](https://github.com/expo/eas-cli/pull/2250) by [@wschurman](https://github.com/wschurman))
- Upgrade [`eas-build`](https://github.com/expo/eas-build) dependencies. ([#2259](https://github.com/expo/eas-cli/pull/2259) by [@expo-bot](https://github.com/expo-bot))
## [7.3.0](https://github.com/expo/eas-cli/releases/tag/v7.3.0) - 2024-02-19
### 🎉 New features
- Fix expo-updates fingerprinting during update. ([#2231](https://github.com/expo/eas-cli/pull/2231) by [@wschurman](https://github.com/wschurman))
### 🐛 Bug fixes
- Don't require expo on fresh react-native project. ([#2235](https://github.com/expo/eas-cli/pull/2235) by [@radoslawkrzemien](https://github.com/radoslawkrzemien))
### 🧹 Chores
- Upgrade [`eas-build`](https://github.com/expo/eas-build) dependencies. ([#2229](https://github.com/expo/eas-cli/pull/2229) by [@expo-bot](https://github.com/expo-bot))
- Upgrade [`eas-build`](https://github.com/expo/eas-build) dependencies. ([#2230](https://github.com/expo/eas-cli/pull/2230) by [@expo-bot](https://github.com/expo-bot))
- Reword update configuration warning. ([#2234](https://github.com/expo/eas-cli/pull/2234) by [@quinlanj](https://github.com/quinlanj))
## [7.2.0](https://github.com/expo/eas-cli/releases/tag/v7.2.0) - 2024-02-11
### 🎉 New features
- Support configuring a Google Service Account Key via eas credentials, for sending Android Notifications via FCM V1. ([#2197](https://github.com/expo/eas-cli/pull/2197) by [@christopherwalter](https://github.com/christopherwalter))
### 🐛 Bug fixes
- Revert expose expo export dev flag as an option in eas update. ([#2214](https://github.com/expo/eas-cli/pull/2214) by [@wschurman](https://github.com/wschurman))
### 🧹 Chores
- Upgrade [`eas-build`](https://github.com/expo/eas-build) dependencies. ([#2223](https://github.com/expo/eas-cli/pull/2223) by [@expo-bot](https://github.com/expo-bot))
## [7.1.3](https://github.com/expo/eas-cli/releases/tag/v7.1.3) - 2024-02-07
### 🧹 Chores
- Remove duplicated log message when creating ASC API key. ([#2208](https://github.com/expo/eas-cli/pull/2208) by [@radoslawkrzemien](https://github.com/radoslawkrzemien))
- Add simulator flag to metadata. ([#2073](https://github.com/expo/eas-cli/pull/2073) by [@radoslawkrzemien](https://github.com/radoslawkrzemien))
- Upgrade [`eas-build`](https://github.com/expo/eas-build) dependencies. ([#2220](https://github.com/expo/eas-cli/pull/2220) by [@expo-bot](https://github.com/expo-bot))
## [7.1.2](https://github.com/expo/eas-cli/releases/tag/v7.1.2) - 2024-01-30
### 🧹 Chores
- Add better validation for EAS Submit inputs. ([#2202](https://github.com/expo/eas-cli/pull/2202) by [@szdziedzic](https://github.com/szdziedzic))
## [7.1.1](https://github.com/expo/eas-cli/releases/tag/v7.1.1) - 2024-01-26
### 🐛 Bug fixes
- Revert incorrect EAS Submit input validation changes. ([#2200](https://github.com/expo/eas-cli/pull/2200) by [@szdziedzic](https://github.com/szdziedzic))
## [7.1.0](https://github.com/expo/eas-cli/releases/tag/v7.1.0) - 2024-01-26
### 🎉 New features
- Support requireCommit for EAS Update. ([#2196](https://github.com/expo/eas-cli/pull/2196) by [@wschurman](https://github.com/wschurman))
### 🧹 Chores
- Remove support for classic updates release channel in 50+. ([#2189](https://github.com/expo/eas-cli/pull/2189) by [@wschurman](https://github.com/wschurman))
- Validate EAS Submit inputs better. ([#2198](https://github.com/expo/eas-cli/pull/2198) by [@szdziedzic](https://github.com/szdziedzic))
## [7.0.0](https://github.com/expo/eas-cli/releases/tag/v7.0.0) - 2024-01-19
### 🛠 Breaking changes
- Stop generating eas-update-metadata.json on publish. ([#2187](https://github.com/expo/eas-cli/pull/2187) by [@quinlanj](https://github.com/quinlanj))
### 🧹 Chores
- Use branch mapping utility fn. ([#2186](https://github.com/expo/eas-cli/pull/2186) by [@quinlanj](https://github.com/quinlanj))
## [6.1.0](https://github.com/expo/eas-cli/releases/tag/v6.1.0) - 2024-01-18
### 🎉 New features
- Add `build:delete` command. ([#2178](https://github.com/expo/eas-cli/pull/2178) by [@radoslawkrzemien](https://github.com/radoslawkrzemien))
- Add filter flags for `platform` and `profile` to `build:cancel` and `build:delete` commands. ([#2178](https://github.com/expo/eas-cli/pull/2178) by [@radoslawkrzemien](https://github.com/radoslawkrzemien))
### 🐛 Bug fixes
### 🧹 Chores
- Remove "bare"-specific **eas.json** template. ([#2179](https://github.com/expo/eas-cli/pull/2179) by [@sjchmiela](https://github.com/sjchmiela))
- Prompt users if they want to continue if EAS CLI fails to provision the devices. ([#2181](https://github.com/expo/eas-cli/pull/2181) by [@szdziedzic](https://github.com/szdziedzic))
- Update `eas-cli` and `@expo/eas-json` dependencies. ([#2176](https://github.com/expo/eas-cli/pull/2176) by [@szdziedzic](https://github.com/szdziedzic))
- Update `eas.schema.json` to after adding Xcode 15.2 image. ([#2184](https://github.com/expo/eas-cli/pull/2184) by [@szdziedzic](https://github.com/szdziedzic))
- Upgrade packages from the expo/expo repo. ([#2145](https://github.com/expo/eas-cli/pull/2145) by [@wschurman](https://github.com/wschurman))
- Prompt user to map channel on update if unmapped. ([#2185](https://github.com/expo/eas-cli/pull/2185) by [@quinlanj](https://github.com/quinlanj))
## [6.0.0](https://github.com/expo/eas-cli/releases/tag/v6.0.0) - 2024-01-12
+6 -6
View File
@@ -1,10 +1,10 @@
* @szdziedzic @khamilowicz @sjchmiela
* @szdziedzic @khamilowicz
packages/eas-cli/src/build @szdziedzic @khamilowicz @sjchmiela
packages/eas-cli/src/commands/build @szdziedzic @khamilowicz @sjchmiela
packages/eas-cli/src/build @szdziedzic @khamilowicz
packages/eas-cli/src/commands/build @szdziedzic @khamilowicz
packages/eas-cli/src/submit @szdziedzic @khamilowicz @sjchmiela
packages/eas-cli/src/commands/submit.ts @szdziedzic @khamilowicz @sjchmiela
packages/eas-cli/src/submit @szdziedzic @khamilowicz
packages/eas-cli/src/commands/submit.ts @szdziedzic @khamilowicz
packages/eas-cli/src/update @EvanBacon @byCedric @wschurman
packages/eas-cli/src/commands/update @EvanBacon @byCedric @wschurman
@@ -13,4 +13,4 @@ packages/eas-cli/schema @bycedric
packages/eas-cli/src/metadata @bycedric
packages/eas-cli/src/commands/metadata @bycedric
packages/eas-json @szdziedzic @khamilowicz @sjchmiela
packages/eas-json @szdziedzic @khamilowicz
+4
View File
@@ -12,3 +12,7 @@ The algorithm works as follows:
- If there are any entries in the "🛠 Breaking changes" section, bump the MAJOR version.
- Otherwise, if there are any entries in the "🎉 New features", bump the MINOR version.
- Otherwise, bump the PATCH version.
## Updating EAS CLI version on EAS Build
The release process promotes the new version to staging. After verifying it works there, you can promote it to production with `npm dist-tag add eas-cli@{version} latest-eas-build`.
+1 -1
View File
@@ -1,5 +1,5 @@
{
"npmClient": "yarn",
"version": "7.6.2",
"version": "6.0.0",
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
}
+63 -87
View File
@@ -68,7 +68,6 @@ eas --help COMMAND
* [`eas build`](#eas-build)
* [`eas build:cancel [BUILD_ID]`](#eas-buildcancel-build_id)
* [`eas build:configure`](#eas-buildconfigure)
* [`eas build:delete [BUILD_ID]`](#eas-builddelete-build_id)
* [`eas build:inspect`](#eas-buildinspect)
* [`eas build:list`](#eas-buildlist)
* [`eas build:resign`](#eas-buildresign)
@@ -136,7 +135,7 @@ ALIASES
$ eas login
```
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/account/login.ts)_
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/account/login.ts)_
## `eas account:logout`
@@ -153,7 +152,7 @@ ALIASES
$ eas logout
```
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/account/logout.ts)_
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/account/logout.ts)_
## `eas account:view`
@@ -170,7 +169,7 @@ ALIASES
$ eas whoami
```
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/account/view.ts)_
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/account/view.ts)_
## `eas analytics [STATUS]`
@@ -184,7 +183,7 @@ DESCRIPTION
display or change analytics settings
```
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/analytics.ts)_
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/analytics.ts)_
## `eas autocomplete [SHELL]`
@@ -236,7 +235,7 @@ DESCRIPTION
create a branch
```
_See code: [src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/branch/create.ts)_
_See code: [src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/branch/create.ts)_
## `eas branch:delete [NAME]`
@@ -257,7 +256,7 @@ DESCRIPTION
delete a branch
```
_See code: [src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/branch/delete.ts)_
_See code: [src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/branch/delete.ts)_
## `eas branch:list`
@@ -277,7 +276,7 @@ DESCRIPTION
list all branches
```
_See code: [src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/branch/list.ts)_
_See code: [src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/branch/list.ts)_
## `eas branch:rename`
@@ -297,7 +296,7 @@ DESCRIPTION
rename a branch
```
_See code: [src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/branch/rename.ts)_
_See code: [src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/branch/rename.ts)_
## `eas branch:view [NAME]`
@@ -320,7 +319,7 @@ DESCRIPTION
view a branch
```
_See code: [src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/branch/view.ts)_
_See code: [src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/branch/view.ts)_
## `eas build`
@@ -350,7 +349,7 @@ DESCRIPTION
start a build
```
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/build/index.ts)_
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/build/index.ts)_
## `eas build:cancel [BUILD_ID]`
@@ -358,18 +357,16 @@ cancel a build
```
USAGE
$ eas build:cancel [BUILD_ID] [--non-interactive] [-p android|ios|all] [-e <value>]
$ eas build:cancel [BUILD_ID] [--non-interactive]
FLAGS
-e, --profile=PROFILE_NAME Filter builds by build profile if build ID is not provided
-p, --platform=(android|ios|all) Filter builds by the platform if build ID is not provided
--non-interactive Run the command in non-interactive mode.
--non-interactive Run the command in non-interactive mode.
DESCRIPTION
cancel a build
```
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/build/cancel.ts)_
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/build/cancel.ts)_
## `eas build:configure`
@@ -386,26 +383,7 @@ DESCRIPTION
configure the project to support EAS Build
```
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/build/configure.ts)_
## `eas build:delete [BUILD_ID]`
delete a build
```
USAGE
$ eas build:delete [BUILD_ID] [--non-interactive] [-p android|ios|all] [-e <value>]
FLAGS
-e, --profile=PROFILE_NAME Filter builds by build profile if build ID is not provided
-p, --platform=(android|ios|all) Filter builds by the platform if build ID is not provided
--non-interactive Run the command in non-interactive mode.
DESCRIPTION
delete a build
```
_See code: [src/commands/build/delete.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/build/delete.ts)_
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/build/configure.ts)_
## `eas build:inspect`
@@ -440,7 +418,7 @@ 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/v7.6.2/src/commands/build/inspect.ts)_
_See code: [src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/build/inspect.ts)_
## `eas build:list`
@@ -452,7 +430,7 @@ USAGE
new|in-queue|in-progress|pending-cancel|errored|finished|canceled] [--distribution store|internal|simulator]
[--channel <value>] [--appVersion <value>] [--appBuildVersion <value>] [--sdkVersion <value>] [--runtimeVersion
<value>] [--appIdentifier <value>] [--buildProfile <value>] [--gitCommitHash <value>] [--offset <value>] [--limit
<value>] [--json --non-interactive] [--simulator]
<value>] [--json --non-interactive]
FLAGS
--appBuildVersion=<value>
@@ -472,16 +450,13 @@ FLAGS
--platform=(all|android|ios)
--runtimeVersion=<value>
--sdkVersion=<value>
--simulator Filter only iOS simulator builds. Can
only be used with --platform flag set to
"ios"
--status=(new|in-queue|in-progress|pending-cancel|errored|finished|canceled)
DESCRIPTION
list all builds for your project
```
_See code: [src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/build/list.ts)_
_See code: [src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/build/list.ts)_
## `eas build:resign`
@@ -507,7 +482,7 @@ DESCRIPTION
re-sign a build archive
```
_See code: [src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/build/resign.ts)_
_See code: [src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/build/resign.ts)_
## `eas build:run`
@@ -533,7 +508,7 @@ DESCRIPTION
run simulator/emulator builds from eas-cli
```
_See code: [src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/build/run.ts)_
_See code: [src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/build/run.ts)_
## `eas build:submit`
@@ -582,7 +557,7 @@ DESCRIPTION
get the latest version from EAS servers
```
_See code: [src/commands/build/version/get.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/build/version/get.ts)_
_See code: [src/commands/build/version/get.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/build/version/get.ts)_
## `eas build:version:set`
@@ -601,7 +576,7 @@ DESCRIPTION
update version of an app
```
_See code: [src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/build/version/set.ts)_
_See code: [src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/build/version/set.ts)_
## `eas build:version:sync`
@@ -620,7 +595,7 @@ DESCRIPTION
update a version in native code with a value stored on EAS servers
```
_See code: [src/commands/build/version/sync.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/build/version/sync.ts)_
_See code: [src/commands/build/version/sync.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/build/version/sync.ts)_
## `eas build:view [BUILD_ID]`
@@ -637,7 +612,7 @@ DESCRIPTION
view a build for your project
```
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/build/view.ts)_
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/build/view.ts)_
## `eas channel:create [NAME]`
@@ -658,7 +633,7 @@ DESCRIPTION
create a channel
```
_See code: [src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/channel/create.ts)_
_See code: [src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/channel/create.ts)_
## `eas channel:edit [NAME]`
@@ -680,7 +655,7 @@ DESCRIPTION
point a channel at a new branch
```
_See code: [src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/channel/edit.ts)_
_See code: [src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/channel/edit.ts)_
## `eas channel:list`
@@ -700,7 +675,7 @@ DESCRIPTION
list all channels
```
_See code: [src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/channel/list.ts)_
_See code: [src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/channel/list.ts)_
## `eas channel:rollout [CHANNEL]`
@@ -732,7 +707,7 @@ DESCRIPTION
Roll a new branch out on a channel incrementally.
```
_See code: [src/commands/channel/rollout.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/channel/rollout.ts)_
_See code: [src/commands/channel/rollout.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/channel/rollout.ts)_
## `eas channel:view [NAME]`
@@ -755,7 +730,7 @@ DESCRIPTION
view a channel
```
_See code: [src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/channel/view.ts)_
_See code: [src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/channel/view.ts)_
## `eas config`
@@ -776,7 +751,7 @@ DESCRIPTION
display project configuration (app.json + eas.json)
```
_See code: [src/commands/config.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/config.ts)_
_See code: [src/commands/config.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/config.ts)_
## `eas credentials`
@@ -793,7 +768,7 @@ DESCRIPTION
manage credentials
```
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/credentials.ts)_
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/credentials.ts)_
## `eas device:create`
@@ -807,7 +782,7 @@ DESCRIPTION
register new Apple Devices to use for internal distribution
```
_See code: [src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/device/create.ts)_
_See code: [src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/device/create.ts)_
## `eas device:delete`
@@ -827,7 +802,7 @@ DESCRIPTION
remove a registered device from your account
```
_See code: [src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/device/delete.ts)_
_See code: [src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/device/delete.ts)_
## `eas device:list`
@@ -848,7 +823,7 @@ DESCRIPTION
list all registered devices for your account
```
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/device/list.ts)_
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/device/list.ts)_
## `eas device:rename`
@@ -869,7 +844,7 @@ DESCRIPTION
rename a registered device
```
_See code: [src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/device/rename.ts)_
_See code: [src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/device/rename.ts)_
## `eas device:view [UDID]`
@@ -883,7 +858,7 @@ DESCRIPTION
view a device for your project
```
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/device/view.ts)_
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/device/view.ts)_
## `eas diagnostics`
@@ -897,7 +872,7 @@ DESCRIPTION
display environment info
```
_See code: [src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/diagnostics.ts)_
_See code: [src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/diagnostics.ts)_
## `eas help [COMMAND]`
@@ -985,7 +960,7 @@ DESCRIPTION
validate the local store configuration
```
_See code: [src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/metadata/lint.ts)_
_See code: [src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/metadata/lint.ts)_
## `eas metadata:pull`
@@ -1002,7 +977,7 @@ DESCRIPTION
generate the local store configuration from the app stores
```
_See code: [src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/metadata/pull.ts)_
_See code: [src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/metadata/pull.ts)_
## `eas metadata:push`
@@ -1019,7 +994,7 @@ DESCRIPTION
sync the local store configuration to the app stores
```
_See code: [src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/metadata/push.ts)_
_See code: [src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/metadata/push.ts)_
## `eas open`
@@ -1033,7 +1008,7 @@ DESCRIPTION
open the project page in a web browser
```
_See code: [src/commands/open.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/open.ts)_
_See code: [src/commands/open.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/open.ts)_
## `eas project:info`
@@ -1047,7 +1022,7 @@ DESCRIPTION
information about the current project
```
_See code: [src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/project/info.ts)_
_See code: [src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/project/info.ts)_
## `eas project:init`
@@ -1069,7 +1044,7 @@ ALIASES
$ eas init
```
_See code: [src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/project/init.ts)_
_See code: [src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/project/init.ts)_
## `eas secret:create`
@@ -1092,7 +1067,7 @@ 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/v7.6.2/src/commands/secret/create.ts)_
_See code: [src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/secret/create.ts)_
## `eas secret:delete`
@@ -1110,7 +1085,7 @@ DESCRIPTION
delete an environment secret by ID
```
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/secret/delete.ts)_
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/secret/delete.ts)_
## `eas secret:list`
@@ -1124,7 +1099,7 @@ DESCRIPTION
list environment secrets available for your current app
```
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/secret/list.ts)_
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/secret/list.ts)_
## `eas secret:push`
@@ -1144,7 +1119,7 @@ DESCRIPTION
read environment secrets from env file and store on the server
```
_See code: [src/commands/secret/push.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/secret/push.ts)_
_See code: [src/commands/secret/push.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/secret/push.ts)_
## `eas submit`
@@ -1174,7 +1149,7 @@ ALIASES
$ eas build:submit
```
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/submit.ts)_
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/submit.ts)_
## `eas update`
@@ -1183,8 +1158,8 @@ publish an update group
```
USAGE
$ eas update [--branch <value>] [--channel <value>] [-m <value>] [--republish | --input-dir <value> |
--skip-bundler] [--group <value> | | ] [--clear-cache] [-p android|ios|all] [--auto] [--private-key-path <value>]
[--json --non-interactive]
--skip-bundler] [--group <value> | | ] [--clear-cache] [-p android|ios|all] [--dev] [--auto] [--private-key-path
<value>] [--json --non-interactive]
FLAGS
-m, --message=<value> A short message describing the update
@@ -1193,6 +1168,7 @@ FLAGS
--branch=<value> Branch to publish the update group on
--channel=<value> Channel that the published update should affect
--clear-cache Clear the bundler cache before publishing
--dev Publish a development bundle
--group=<value> Update group to republish (deprecated, see republish command)
--input-dir=<value> [default: dist] Location of the bundle
--json Enable JSON output, non-JSON messages will be printed to stderr.
@@ -1207,7 +1183,7 @@ DESCRIPTION
publish an update group
```
_See code: [src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/update/index.ts)_
_See code: [src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/update/index.ts)_
## `eas update:configure`
@@ -1225,7 +1201,7 @@ DESCRIPTION
configure the project to support EAS Update
```
_See code: [src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/update/configure.ts)_
_See code: [src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/update/configure.ts)_
## `eas update:delete GROUPID`
@@ -1246,7 +1222,7 @@ DESCRIPTION
delete all the updates in an update group
```
_See code: [src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/update/delete.ts)_
_See code: [src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/update/delete.ts)_
## `eas update:list`
@@ -1268,7 +1244,7 @@ DESCRIPTION
view the recent updates
```
_See code: [src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/update/list.ts)_
_See code: [src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/update/list.ts)_
## `eas update:republish`
@@ -1295,7 +1271,7 @@ DESCRIPTION
roll back to an existing update
```
_See code: [src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/update/republish.ts)_
_See code: [src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/update/republish.ts)_
## `eas update:roll-back-to-embedded`
@@ -1322,7 +1298,7 @@ DESCRIPTION
roll back to the embedded update
```
_See code: [src/commands/update/roll-back-to-embedded.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/update/roll-back-to-embedded.ts)_
_See code: [src/commands/update/roll-back-to-embedded.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/update/roll-back-to-embedded.ts)_
## `eas update:rollback`
@@ -1341,7 +1317,7 @@ DESCRIPTION
roll back to an embedded update or an existing update
```
_See code: [src/commands/update/rollback.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/update/rollback.ts)_
_See code: [src/commands/update/rollback.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/update/rollback.ts)_
## `eas update:view GROUPID`
@@ -1361,7 +1337,7 @@ DESCRIPTION
update group details
```
_See code: [src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/update/view.ts)_
_See code: [src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/update/view.ts)_
## `eas webhook:create`
@@ -1382,7 +1358,7 @@ DESCRIPTION
create a webhook
```
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/webhook/create.ts)_
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/webhook/create.ts)_
## `eas webhook:delete [ID]`
@@ -1402,7 +1378,7 @@ DESCRIPTION
delete a webhook
```
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/webhook/delete.ts)_
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/webhook/delete.ts)_
## `eas webhook:list`
@@ -1420,7 +1396,7 @@ DESCRIPTION
list webhooks
```
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/webhook/list.ts)_
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/webhook/list.ts)_
## `eas webhook:update`
@@ -1442,7 +1418,7 @@ DESCRIPTION
update a webhook
```
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/webhook/update.ts)_
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/webhook/update.ts)_
## `eas webhook:view ID`
@@ -1459,7 +1435,7 @@ DESCRIPTION
view a webhook
```
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v7.6.2/src/commands/webhook/view.ts)_
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/webhook/view.ts)_
## `eas whoami`
-260
View File
@@ -4726,18 +4726,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "googleServiceAccountKeyForFcmV1",
"description": null,
"args": [],
"type": {
"kind": "OBJECT",
"name": "GoogleServiceAccountKey",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "googleServiceAccountKeyForSubmissions",
"description": null,
@@ -4841,18 +4829,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "googleServiceAccountKeyForFcmV1Id",
"description": null,
"type": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "googleServiceAccountKeyForSubmissionsId",
"description": null,
@@ -4940,71 +4916,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "createFcmV1Credential",
"description": "Create a GoogleServiceAccountKeyEntity to store credential and\nconnect it with an edge from AndroidAppCredential",
"args": [
{
"name": "accountId",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "androidAppCredentialsId",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "credential",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "AndroidAppCredentials",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "deleteAndroidAppCredentials",
"description": "Delete a set of credentials for an Android app",
@@ -5087,55 +4998,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "setGoogleServiceAccountKeyForFcmV1",
"description": "Set the Google Service Account Key to be used for Firebase Cloud Messaging V1",
"args": [
{
"name": "googleServiceAccountKeyId",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "id",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "AndroidAppCredentials",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "setGoogleServiceAccountKeyForSubmissions",
"description": "Set the Google Service Account Key to be used for submitting an Android app",
@@ -14711,22 +14573,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "isForIosSimulator",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "isGitWorkingTreeDirty",
"description": null,
@@ -16026,18 +15872,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "simulator",
"description": null,
"type": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "status",
"description": null,
@@ -16136,18 +15970,6 @@
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "simulator",
"description": null,
"type": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"interfaces": null,
@@ -17072,18 +16894,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "simulator",
"description": null,
"type": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "trackingContext",
"description": null,
@@ -18149,22 +17959,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "isForIosSimulator",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "platform",
"description": null,
@@ -19536,18 +19330,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "submitProfile",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "targetPattern",
"description": "A branch name or a wildcard pattern that the pull request targets. For example, `main` or `release/*`.",
@@ -23460,18 +23242,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "submitProfile",
"description": null,
"args": [],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "targetPattern",
"description": null,
@@ -27730,12 +27500,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "DID_SUBSCRIBE_TO_EAS_AT_LEAST_ONCE",
"description": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "EAS_MASTER_LIST",
"description": null,
@@ -28683,12 +28447,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "BUILD_ERRORED",
"description": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "BUILD_LIMIT_THRESHOLD_EXCEEDED",
"description": null,
@@ -28707,12 +28465,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "SUBMISSION_ERRORED",
"description": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "TEST",
"description": null,
@@ -37298,18 +37050,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "submitProfile",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "targetPattern",
"description": null,
+9 -9
View File
@@ -1,20 +1,20 @@
{
"name": "eas-cli",
"description": "EAS command line tool",
"version": "7.6.2",
"version": "6.0.0",
"author": "Expo <[email protected]>",
"bin": {
"eas": "./bin/run"
},
"bugs": "https://github.com/expo/eas-cli/issues",
"dependencies": {
"@expo/apple-utils": "1.7.0",
"@expo/apple-utils": "1.3.2",
"@expo/code-signing-certificates": "0.0.5",
"@expo/config": "8.5.4",
"@expo/config-plugins": "7.8.4",
"@expo/config-types": "50.0.0",
"@expo/eas-build-job": "1.0.88",
"@expo/eas-json": "7.6.1",
"@expo/config": "8.1.2",
"@expo/config-plugins": "7.2.4",
"@expo/config-types": "49.0.0",
"@expo/eas-build-job": "1.0.56",
"@expo/eas-json": "6.0.0",
"@expo/json-file": "8.2.37",
"@expo/multipart-body-parser": "1.1.0",
"@expo/osascript": "2.0.33",
@@ -23,11 +23,11 @@
"@expo/plist": "0.0.20",
"@expo/plugin-help": "5.1.23",
"@expo/plugin-warn-if-update-available": "2.5.1",
"@expo/prebuild-config": "6.7.3",
"@expo/prebuild-config": "6.2.5",
"@expo/results": "1.0.0",
"@expo/rudder-sdk-node": "1.1.1",
"@expo/spawn-async": "1.7.0",
"@expo/steps": "1.0.91",
"@expo/steps": "1.0.51",
"@expo/timeago.js": "1.0.0",
"@oclif/core": "^1.26.2",
"@oclif/plugin-autocomplete": "^2.3.10",
@@ -92,6 +92,5 @@ function createMockBuildFragment({
},
status: BuildStatus.InQueue,
resourceClass: BuildResourceClass.AndroidMedium,
isForIosSimulator: false,
};
}
@@ -92,6 +92,5 @@ function createMockBuildFragment({
},
status: BuildStatus.InQueue,
resourceClass: BuildResourceClass.AndroidMedium,
isForIosSimulator: false,
};
}
@@ -8,7 +8,7 @@ import os from 'os';
import path from 'path';
import { getAppBuildGradleAsync, resolveConfigValue } from '../../../project/android/gradleUtils';
import { resolveVcsClient } from '../../../vcs';
import { getVcsClient } from '../../../vcs';
import {
BumpStrategy,
bumpVersionAsync,
@@ -19,7 +19,7 @@ import {
const fsReal = jest.requireActual('fs').promises as typeof fs;
jest.mock('fs');
const vcsClient = resolveVcsClient();
const vcsClient = getVcsClient();
afterAll(async () => {
// do not remove the following line
+2 -1
View File
@@ -99,13 +99,14 @@ export async function prepareAndroidBuildAsync(
return await ensureAndroidCredentialsAsync(ctx);
},
syncProjectConfigurationAsync: async () => {
await syncProjectConfigurationAsync({
await syncProjectConfigurationAsync(ctx.graphqlClient, {
projectDir: ctx.projectDir,
exp: ctx.exp,
localAutoIncrement:
ctx.easJsonCliConfig?.appVersionSource === AppVersionSource.REMOTE
? false
: ctx.buildProfile.autoIncrement,
projectId: ctx.projectId,
vcsClient: ctx.vcsClient,
});
},
@@ -12,7 +12,7 @@ import path from 'path';
import slash from 'slash';
import { AndroidCredentials } from '../../credentials/android/AndroidCredentialsProvider';
import { getCustomBuildConfigPathForJob } from '../../project/customBuildConfig';
import { getCustomBuildConfigPath } from '../../project/customBuildConfig';
import { getUsername } from '../../project/projectUtils';
import { BuildContext } from '../context';
@@ -54,7 +54,7 @@ export async function prepareJobAsync(
}
const maybeCustomBuildConfigPath = buildProfile.config
? getCustomBuildConfigPathForJob(buildProfile.config)
? getCustomBuildConfigPath(buildProfile.config)
: undefined;
const job: Android.Job = {
@@ -7,30 +7,36 @@ import fs from 'fs-extra';
import path from 'path';
import { BumpStrategy, bumpVersionAsync, bumpVersionInAppJsonAsync } from './version';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import Log from '../../log';
import { isExpoUpdatesInstalled } from '../../project/projectUtils';
import { resolveWorkflowAsync } from '../../project/workflow';
import { syncUpdatesConfigurationAsync } from '../../update/android/UpdatesModule';
import { Client } from '../../vcs/vcs';
export async function syncProjectConfigurationAsync({
projectDir,
exp,
localAutoIncrement,
vcsClient,
}: {
projectDir: string;
exp: ExpoConfig;
localAutoIncrement?: AndroidVersionAutoIncrement;
vcsClient: Client;
}): Promise<void> {
export async function syncProjectConfigurationAsync(
graphqlClient: ExpoGraphqlClient,
{
projectDir,
exp,
localAutoIncrement,
projectId,
vcsClient,
}: {
projectDir: string;
exp: ExpoConfig;
localAutoIncrement?: AndroidVersionAutoIncrement;
projectId: string;
vcsClient: Client;
}
): Promise<void> {
const workflow = await resolveWorkflowAsync(projectDir, Platform.ANDROID, vcsClient);
const versionBumpStrategy = resolveVersionBumpStrategy(localAutoIncrement ?? false);
if (workflow === Workflow.GENERIC) {
await cleanUpOldEasBuildGradleScriptAsync(projectDir);
if (isExpoUpdatesInstalled(projectDir)) {
await syncUpdatesConfigurationAsync(projectDir, exp);
await syncUpdatesConfigurationAsync(graphqlClient, projectDir, exp, projectId);
}
await bumpVersionAsync({ projectDir, exp, bumpStrategy: versionBumpStrategy });
} else {
@@ -232,9 +232,7 @@ export async function resolveRemoteVersionCodeAsync(
applicationIdentifier: applicationId,
storeVersion: localVersions.appVersion ?? exp.version ?? '1.0.0',
buildVersion: currentBuildVersion,
runtimeVersion:
(await Updates.getRuntimeVersionNullableAsync(projectDir, exp, Platform.ANDROID)) ??
undefined,
runtimeVersion: Updates.getRuntimeVersionNullable(exp, Platform.ANDROID) ?? undefined,
});
spinner.succeed(`Initialized versionCode with ${chalk.bold(currentBuildVersion)}.`);
} catch (err) {
@@ -256,9 +254,7 @@ export async function resolveRemoteVersionCodeAsync(
applicationIdentifier: applicationId,
storeVersion: localVersions.appVersion ?? exp.version ?? '1.0.0',
buildVersion: String(nextBuildVersion),
runtimeVersion:
(await Updates.getRuntimeVersionNullableAsync(projectDir, exp, Platform.ANDROID)) ??
undefined,
runtimeVersion: Updates.getRuntimeVersionNullable(exp, Platform.ANDROID) ?? undefined,
});
spinner.succeed(
`Incremented versionCode from ${chalk.bold(currentBuildVersion)} to ${chalk.bold(
+1 -1
View File
@@ -40,7 +40,7 @@ async function configureAsync({
nonInteractive,
vcsClient,
}: ConfigureParams): Promise<void> {
await maybeBailOnRepoStatusAsync(vcsClient, nonInteractive);
await maybeBailOnRepoStatusAsync(vcsClient);
await createEasJsonAsync(projectDir, vcsClient);
@@ -6,7 +6,7 @@ import os from 'os';
import type { XCBuildConfiguration } from 'xcode';
import { readPlistAsync } from '../../../utils/plist';
import { resolveVcsClient } from '../../../vcs';
import { getVcsClient } from '../../../vcs';
import {
BumpStrategy,
bumpVersionAsync,
@@ -19,7 +19,7 @@ import {
jest.mock('fs');
const vcsClient = resolveVcsClient();
const vcsClient = getVcsClient();
const getXCBuildConfigurationFromPbxproj = jest.spyOn(
IOSConfig.Target,
+2 -1
View File
@@ -80,7 +80,7 @@ export async function prepareIosBuildAsync(
return ensureIosCredentialsAsync(ctx, ctx.ios.targets);
},
syncProjectConfigurationAsync: async () => {
await syncProjectConfigurationAsync({
await syncProjectConfigurationAsync(ctx.graphqlClient, {
projectDir: ctx.projectDir,
exp: ctx.exp,
targets: ctx.ios.targets,
@@ -88,6 +88,7 @@ export async function prepareIosBuildAsync(
ctx.easJsonCliConfig?.appVersionSource === AppVersionSource.REMOTE
? false
: ctx.buildProfile.autoIncrement,
projectId: ctx.projectId,
vcsClient: ctx.vcsClient,
});
},
+2 -2
View File
@@ -14,7 +14,7 @@ import slash from 'slash';
import { IosCredentials, TargetCredentials } from '../../credentials/ios/types';
import { IosJobSecretsInput } from '../../graphql/generated';
import { getCustomBuildConfigPathForJob } from '../../project/customBuildConfig';
import { getCustomBuildConfigPath } from '../../project/customBuildConfig';
import { getUsername } from '../../project/projectUtils';
import { BuildContext } from '../context';
@@ -46,7 +46,7 @@ export async function prepareJobAsync(
}
const maybeCustomBuildConfigPath = buildProfile.config
? getCustomBuildConfigPathForJob(buildProfile.config)
? getCustomBuildConfigPath(buildProfile.config)
: undefined;
const job: Ios.Job = {
@@ -3,31 +3,37 @@ import { Platform, Workflow } from '@expo/eas-build-job';
import { IosVersionAutoIncrement } from '@expo/eas-json';
import { BumpStrategy, bumpVersionAsync, bumpVersionInAppJsonAsync } from './version';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { Target } from '../../credentials/ios/types';
import { isExpoUpdatesInstalled } from '../../project/projectUtils';
import { resolveWorkflowAsync } from '../../project/workflow';
import { syncUpdatesConfigurationAsync } from '../../update/ios/UpdatesModule';
import { Client } from '../../vcs/vcs';
export async function syncProjectConfigurationAsync({
projectDir,
exp,
targets,
localAutoIncrement,
vcsClient,
}: {
projectDir: string;
exp: ExpoConfig;
targets: Target[];
localAutoIncrement?: IosVersionAutoIncrement;
vcsClient: Client;
}): Promise<void> {
export async function syncProjectConfigurationAsync(
graphqlClient: ExpoGraphqlClient,
{
projectDir,
exp,
targets,
localAutoIncrement,
projectId,
vcsClient,
}: {
projectDir: string;
exp: ExpoConfig;
targets: Target[];
localAutoIncrement?: IosVersionAutoIncrement;
projectId: string;
vcsClient: Client;
}
): Promise<void> {
const workflow = await resolveWorkflowAsync(projectDir, Platform.IOS, vcsClient);
const versionBumpStrategy = resolveVersionBumpStrategy(localAutoIncrement ?? false);
if (workflow === Workflow.GENERIC) {
if (isExpoUpdatesInstalled(projectDir)) {
await syncUpdatesConfigurationAsync(vcsClient, projectDir, exp);
await syncUpdatesConfigurationAsync(graphqlClient, vcsClient, projectDir, exp, projectId);
}
await bumpVersionAsync({ projectDir, exp, bumpStrategy: versionBumpStrategy, targets });
} else {
+2 -6
View File
@@ -342,9 +342,7 @@ export async function resolveRemoteBuildNumberAsync(
applicationIdentifier: applicationTarget.bundleIdentifier,
storeVersion: localShortVersion ?? '1.0.0',
buildVersion: currentBuildVersion,
runtimeVersion:
(await Updates.getRuntimeVersionNullableAsync(projectDir, exp, Platform.IOS)) ??
undefined,
runtimeVersion: Updates.getRuntimeVersionNullable(exp, Platform.IOS) ?? undefined,
});
spinner.succeed(`Initialized buildNumber with ${chalk.bold(currentBuildVersion)}.`);
} catch (err) {
@@ -366,9 +364,7 @@ export async function resolveRemoteBuildNumberAsync(
applicationIdentifier: applicationTarget.bundleIdentifier,
storeVersion: localShortVersion ?? '1.0.0',
buildVersion: nextBuildVersion,
runtimeVersion:
(await Updates.getRuntimeVersionNullableAsync(projectDir, exp, Platform.IOS)) ??
undefined,
runtimeVersion: Updates.getRuntimeVersionNullable(exp, Platform.IOS) ?? undefined,
});
spinner.succeed(
`Incremented buildNumber from ${chalk.bold(currentBuildVersion)} to ${chalk.bold(
+1 -1
View File
@@ -6,7 +6,7 @@ import semver from 'semver';
import { ora } from '../ora';
const PLUGIN_PACKAGE_NAME = 'eas-cli-local-build-plugin';
const PLUGIN_PACKAGE_VERSION = '1.0.89';
const PLUGIN_PACKAGE_VERSION = '1.0.56';
export enum LocalBuildMode {
/**
+10 -19
View File
@@ -1,3 +1,4 @@
import { Updates } from '@expo/config-plugins';
import { Metadata, Platform, sanitizeMetadata } from '@expo/eas-build-job';
import { IosEnterpriseProvisioning } from '@expo/eas-json';
import fs from 'fs-extra';
@@ -7,14 +8,8 @@ import { maybeResolveVersionsAsync as maybeResolveAndroidVersionsAsync } from '.
import { BuildContext } from './context';
import { maybeResolveVersionsAsync as maybeResolveIosVersionsAsync } from './ios/version';
import { LocalBuildMode } from './local';
import { BuildDistributionType } from './types';
import Log from '../log';
import {
getUsername,
isClassicUpdatesSupportedAsync,
isExpoUpdatesInstalled,
} from '../project/projectUtils';
import { resolveRuntimeVersionAsync } from '../project/resolveRuntimeVersionAsync';
import { getUsername, isExpoUpdatesInstalled } from '../project/projectUtils';
import {
readChannelSafelyAsync as readAndroidChannelSafelyAsync,
readReleaseChannelSafelyAsync as readAndroidReleaseChannelSafelyAsync,
@@ -29,7 +24,10 @@ export async function collectMetadataAsync<T extends Platform>(
ctx: BuildContext<T>
): Promise<Metadata> {
const channelOrReleaseChannel = await resolveChannelOrReleaseChannelAsync(ctx);
const distribution = ctx.buildProfile.distribution ?? BuildDistributionType.STORE;
const distribution =
('simulator' in ctx.buildProfile && ctx.buildProfile.simulator
? 'simulator'
: ctx.buildProfile.distribution) ?? 'store';
const metadata: Metadata = {
trackingContext: ctx.analyticsEventProperties,
...(await maybeResolveVersionsAsync(ctx)),
@@ -37,7 +35,7 @@ export async function collectMetadataAsync<T extends Platform>(
workflow: ctx.workflow,
credentialsSource: ctx.buildProfile.credentialsSource,
sdkVersion: ctx.exp.sdkVersion,
runtimeVersion: (await resolveRuntimeVersionAsync(ctx)) ?? undefined,
runtimeVersion: Updates.getRuntimeVersionNullable(ctx.exp, ctx.platform) ?? undefined,
reactNativeVersion: await getReactNativeVersionAsync(ctx.projectDir),
...channelOrReleaseChannel,
distribution,
@@ -66,7 +64,6 @@ export async function collectMetadataAsync<T extends Platform>(
requiredPackageManager: ctx.requiredPackageManager ?? undefined,
selectedImage: ctx.buildProfile.image,
customNodeVersion: ctx.buildProfile.node,
simulator: 'simulator' in ctx.buildProfile && ctx.buildProfile.simulator,
};
return sanitizeMetadata(metadata);
}
@@ -126,19 +123,13 @@ async function resolveChannelOrReleaseChannelAsync<T extends Platform>(
if (ctx.buildProfile.channel) {
return { channel: ctx.buildProfile.channel };
}
if (ctx.buildProfile.releaseChannel) {
return { releaseChannel: ctx.buildProfile.releaseChannel };
}
const channel = await getNativeChannelAsync(ctx);
if (channel) {
return { channel };
}
if (!(await isClassicUpdatesSupportedAsync(ctx.projectDir))) {
return null;
}
if (ctx.buildProfile.releaseChannel) {
return { releaseChannel: ctx.buildProfile.releaseChannel };
}
const releaseChannel = await getNativeReleaseChannelAsync(ctx);
return { releaseChannel };
}
+12 -25
View File
@@ -19,7 +19,7 @@ import { ensureProjectConfiguredAsync } from './configure';
import { BuildContext } from './context';
import { createBuildContextAsync } from './createContext';
import { prepareIosBuildAsync } from './ios/build';
import { LocalBuildMode, LocalBuildOptions } from './local';
import { LocalBuildOptions } from './local';
import { ensureExpoDevClientInstalledForDevClientBuildsAsync } from './utils/devClient';
import { printBuildResults, printLogsUrls } from './utils/printBuildInfo';
import { ensureRepoIsCleanAsync } from './utils/repository';
@@ -180,23 +180,13 @@ export async function runBuildAndSubmitAsync(
buildCtxByPlatform[platform] = buildCtx;
}
if (flags.localBuildOptions.localBuildMode === LocalBuildMode.LOCAL_BUILD_PLUGIN) {
if (flags.localBuildOptions.localBuildMode) {
return;
}
if (flags.localBuildOptions.localBuildMode === LocalBuildMode.INTERNAL) {
const startedBuild = await BuildQuery.byIdAsync(
graphqlClient,
nullthrows(process.env.EAS_BUILD_ID, 'EAS_BUILD_ID is not defined')
);
startedBuilds.push({ build: startedBuild, buildProfile: buildProfiles[0] });
}
if (!flags.localBuildOptions.localBuildMode) {
Log.newLine();
printLogsUrls(startedBuilds.map(startedBuild => startedBuild.build));
Log.newLine();
}
Log.newLine();
printLogsUrls(startedBuilds.map(startedBuild => startedBuild.build));
Log.newLine();
const submissions: SubmissionFragment[] = [];
if (flags.autoSubmit) {
@@ -229,15 +219,9 @@ export async function runBuildAndSubmitAsync(
submissions.push(submission);
}
if (!flags.localBuildOptions.localBuildMode) {
Log.newLine();
printSubmissionDetailsUrls(submissions);
Log.newLine();
}
}
if (flags.localBuildOptions.localBuildMode) {
return;
Log.newLine();
printSubmissionDetailsUrls(submissions);
Log.newLine();
}
if (!flags.wait) {
@@ -350,6 +334,7 @@ async function prepareAndStartBuildAsync({
);
if (buildProfile.profile.channel) {
await validateExpoUpdatesInstalledAsProjectDependencyAsync({
graphqlClient,
exp: buildCtx.exp,
projectId: buildCtx.projectId,
projectDir,
@@ -494,6 +479,7 @@ async function maybeDownloadAndRunSimulatorBuildsAsync(
async function validateExpoUpdatesInstalledAsProjectDependencyAsync({
exp,
graphqlClient,
projectId,
projectDir,
vcsClient,
@@ -501,6 +487,7 @@ async function validateExpoUpdatesInstalledAsProjectDependencyAsync({
nonInteractive,
sdkVersion,
}: {
graphqlClient: ExpoGraphqlClient;
exp: ExpoConfig;
projectId: string;
projectDir: string;
@@ -529,7 +516,7 @@ async function validateExpoUpdatesInstalledAsProjectDependencyAsync({
message: `Would you like to install the "expo-updates" package and configure EAS Update now?`,
});
if (installExpoUpdates) {
await ensureEASUpdateIsConfiguredAsync({
await ensureEASUpdateIsConfiguredAsync(graphqlClient, {
exp,
projectId,
projectDir,
-1
View File
@@ -11,6 +11,5 @@ export enum BuildStatus {
export enum BuildDistributionType {
STORE = 'store',
INTERNAL = 'internal',
/** @deprecated Use simulator flag instead */
SIMULATOR = 'simulator',
}
+1 -12
View File
@@ -12,10 +12,7 @@ import { getTmpDirectory } from '../../utils/paths';
import { endTimer, formatMilliseconds, startTimer } from '../../utils/timer';
import { Client } from '../../vcs/vcs';
export async function maybeBailOnRepoStatusAsync(
vcsClient: Client,
nonInteractive: boolean
): Promise<void> {
export async function maybeBailOnRepoStatusAsync(vcsClient: Client): Promise<void> {
if (!(await vcsClient.isCommitRequiredAsync())) {
return;
}
@@ -31,11 +28,6 @@ export async function maybeBailOnRepoStatusAsync(
});
if (!answer) {
if (nonInteractive) {
Log.log('The following files need to be committed:');
await vcsClient.showChangedFilesAsync();
}
throw new Error('Commit all changes. Aborting...');
}
}
@@ -55,9 +47,6 @@ export async function ensureRepoIsCleanAsync(
)}.`
);
if (nonInteractive) {
Log.log('The following files need to be committed:');
await vcsClient.showChangedFilesAsync();
throw new Error('Commit all changes. Aborting...');
}
const answer = await confirmAsync({
@@ -24,7 +24,6 @@ import {
} from '../analytics/AnalyticsManager';
import Log from '../log';
import SessionManager from '../user/SessionManager';
import { Client } from '../vcs/vcs';
export type ContextInput<
T extends {
@@ -140,7 +139,7 @@ export default abstract class EasCommand extends Command {
} = object,
>(
commandClass: { contextDefinition: ContextInput<C> },
{ nonInteractive, vcsClientOverride }: { nonInteractive: boolean; vcsClientOverride?: Client }
{ nonInteractive }: { nonInteractive: boolean }
): Promise<ContextOutput<C>> {
const contextDefinition = commandClass.contextDefinition;
@@ -153,7 +152,6 @@ export default abstract class EasCommand extends Command {
nonInteractive,
sessionManager: this.sessionManager,
analytics: this.analytics,
vcsClientOverride,
}),
]);
}
@@ -1,12 +1,10 @@
import { Analytics } from '../../analytics/AnalyticsManager';
import SessionManager from '../../user/SessionManager';
import { Client } from '../../vcs/vcs';
export interface ContextOptions {
sessionManager: SessionManager;
analytics: Analytics;
nonInteractive: boolean;
vcsClientOverride?: Client;
}
export default abstract class ContextField<T> {
@@ -1,18 +1,9 @@
import { EasJsonAccessor, EasJsonUtils } from '@expo/eas-json';
import ContextField from './ContextField';
import { findProjectDirAndVerifyProjectSetupAsync } from './contextUtils/findProjectDirAndVerifyProjectSetupAsync';
import { resolveVcsClient } from '../../vcs';
import { getVcsClient } from '../../vcs';
import { Client } from '../../vcs/vcs';
export default class VcsClientContextField extends ContextField<Client> {
async getValueAsync({ vcsClientOverride }: { vcsClientOverride?: Client }): Promise<Client> {
if (vcsClientOverride) {
return vcsClientOverride;
}
const projectDir = await findProjectDirAndVerifyProjectSetupAsync();
const easJsonAccessor = EasJsonAccessor.fromProjectPath(projectDir);
const config = await EasJsonUtils.getCliConfigAsync(easJsonAccessor);
return resolveVcsClient(config?.requireCommit);
async getValueAsync(): Promise<Client> {
return getVcsClient();
}
}
@@ -8,7 +8,8 @@ import semver from 'semver';
import { learnMore } from '../../../log';
import { easCliVersion } from '../../../utils/easCli';
import { resolveVcsClient } from '../../../vcs';
import { getVcsClient, setVcsClient } from '../../../vcs';
import GitClient from '../../../vcs/clients/git';
async function applyCliConfigAsync(projectDir: string): Promise<void> {
const easJsonAccessor = EasJsonAccessor.fromProjectPath(projectDir);
@@ -18,6 +19,9 @@ async function applyCliConfigAsync(projectDir: string): Promise<void> {
`You are on eas-cli@${easCliVersion} which does not satisfy the CLI version constraint in eas.json (${config.version})`
);
}
if (config?.requireCommit) {
setVcsClient(new GitClient());
}
}
async function ensureEasCliIsNotInDependenciesAsync(projectDir: string): Promise<void> {
@@ -88,7 +92,7 @@ export async function findProjectRootAsync({
} else {
let vcsRoot;
try {
vcsRoot = path.normalize(await resolveVcsClient().getRootPathAsync());
vcsRoot = path.normalize(await getVcsClient().getRootPathAsync());
} catch {}
if (vcsRoot && vcsRoot.startsWith(projectRootDir) && vcsRoot !== projectRootDir) {
throw new Error(
@@ -11,7 +11,10 @@ import { isExpoUpdatesInstalled, isUsingEASUpdate } from '../../project/projectU
import { resolveWorkflowAsync } from '../../project/workflow';
import { promptAsync } from '../../prompts';
import { syncUpdatesConfigurationAsync as syncAndroidUpdatesConfigurationAsync } from '../../update/android/UpdatesModule';
import { ensureEASUpdateIsConfiguredInEasJsonAsync } from '../../update/configure';
import {
ensureEASUpdateIsConfiguredInEasJsonAsync,
ensureUseClassicUpdatesIsRemovedAsync,
} from '../../update/configure';
import { syncUpdatesConfigurationAsync as syncIosUpdatesConfigurationAsync } from '../../update/ios/UpdatesModule';
export default class BuildConfigure extends EasCommand {
@@ -35,6 +38,7 @@ export default class BuildConfigure extends EasCommand {
const { flags } = await this.parse(BuildConfigure);
const {
privateProjectConfig: { exp, projectId, projectDir },
loggedIn: { graphqlClient },
vcsClient,
} = await this.getContextAsync(BuildConfigure, {
nonInteractive: false,
@@ -66,6 +70,12 @@ export default class BuildConfigure extends EasCommand {
vcsClient,
});
if (didCreateEasJson && isUsingEASUpdate(exp, projectId)) {
if (exp.updates?.useClassicUpdates) {
// NOTE: this method modifies the Expo config; be sure to use this function's return value
// if the config object is used later in the future
await ensureUseClassicUpdatesIsRemovedAsync({ exp, projectDir });
}
await ensureEASUpdateIsConfiguredInEasJsonAsync(projectDir);
}
@@ -74,14 +84,20 @@ export default class BuildConfigure extends EasCommand {
if ([RequestedPlatform.Android, RequestedPlatform.All].includes(platform)) {
const workflow = await resolveWorkflowAsync(projectDir, Platform.ANDROID, vcsClient);
if (workflow === Workflow.GENERIC) {
await syncAndroidUpdatesConfigurationAsync(projectDir, exp);
await syncAndroidUpdatesConfigurationAsync(graphqlClient, projectDir, exp, projectId);
}
}
if ([RequestedPlatform.Ios, RequestedPlatform.All].includes(platform)) {
const workflow = await resolveWorkflowAsync(projectDir, Platform.IOS, vcsClient);
if (workflow === Workflow.GENERIC) {
await syncIosUpdatesConfigurationAsync(vcsClient, projectDir, exp);
await syncIosUpdatesConfigurationAsync(
graphqlClient,
vcsClient,
projectDir,
exp,
projectId
);
}
}
}
@@ -6,6 +6,7 @@ import { runBuildAndSubmitAsync } from '../../build/runBuildAndSubmit';
import EasCommand from '../../commandUtils/EasCommand';
import { RequestedPlatform } from '../../platform';
import { enableJsonOutput } from '../../utils/json';
import { setVcsClient } from '../../vcs';
import GitNoCommitClient from '../../vcs/clients/gitNoCommit';
/**
@@ -29,17 +30,6 @@ export default class BuildInternal extends EasCommand {
'Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.',
helpValue: 'PROFILE_NAME',
}),
'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({
description: 'Submit on build complete using the submit profile with provided name',
helpValue: 'PROFILE_NAME',
exclusive: ['auto-submit'],
}),
};
static override contextDefinition = {
@@ -63,9 +53,10 @@ export default class BuildInternal extends EasCommand {
vcsClient,
} = await this.getContextAsync(BuildInternal, {
nonInteractive: true,
vcsClientOverride: new GitNoCommitClient(),
});
setVcsClient(new GitNoCommitClient());
await handleDeprecatedEasJsonAsync(projectDir, flags.nonInteractive);
await runBuildAndSubmitAsync(
@@ -80,11 +71,10 @@ export default class BuildInternal extends EasCommand {
wait: false,
clearCache: false,
json: true,
autoSubmit: flags['auto-submit'] || flags['auto-submit-with-profile'] !== undefined,
autoSubmit: false,
localBuildOptions: {
localBuildMode: LocalBuildMode.INTERNAL,
},
submitProfile: flags['auto-submit-with-profile'] ?? flags.profile,
},
actor,
getDynamicPrivateProjectConfigAsync
@@ -10,7 +10,6 @@ import {
getPaginatedQueryOptions,
} from '../../commandUtils/pagination';
import { AppPlatform, BuildStatus as GraphQLBuildStatus } from '../../graphql/generated';
import Log from '../../log';
import { RequestedPlatform } from '../../platform';
import { getDisplayNameForProjectIdAsync } from '../../project/projectUtils';
import { buildDistributionTypeToGraphQLDistributionType } from '../../utils/buildDistribution';
@@ -52,10 +51,6 @@ export default class BuildList extends EasCommand {
...EasPaginatedQueryFlags,
limit: getLimitFlagWithCustomValues({ defaultTo: 10, limit: BUILDS_LIMIT }),
...EasNonInteractiveAndJsonFlags,
simulator: Flags.boolean({
description:
'Filter only iOS simulator builds. Can only be used with --platform flag set to "ios"',
}),
};
static override contextDefinition = {
@@ -74,17 +69,6 @@ export default class BuildList extends EasCommand {
distribution: buildDistribution,
'non-interactive': nonInteractive,
} = flags;
if (buildDistribution === BuildDistributionType.SIMULATOR) {
Log.warn(
`Using --distribution flag with "simulator" value is deprecated - use --simulator flag instead`
);
}
if (flags.simulator && requestedPlatform !== RequestedPlatform.Ios) {
Log.error(
`The --simulator flag is only usable with --platform flag set to "ios", as it is used to filter specifically iOS simulator builds`
);
process.exit(1);
}
const {
privateProjectConfig: { projectId },
loggedIn: { graphqlClient },
@@ -116,7 +100,6 @@ export default class BuildList extends EasCommand {
appIdentifier: flags.appIdentifier,
buildProfile: flags.buildProfile,
gitCommitHash: flags.gitCommitHash,
simulator: flags.simulator,
},
paginatedQueryOptions,
});
+5 -4
View File
@@ -11,7 +11,7 @@ import {
PaginatedQueryOptions,
getPaginatedQueryOptions,
} from '../../commandUtils/pagination';
import { AppPlatform, BuildFragment, BuildStatus } from '../../graphql/generated';
import { AppPlatform, BuildFragment, BuildStatus, DistributionType } from '../../graphql/generated';
import { BuildQuery } from '../../graphql/queries/BuildQuery';
import Log from '../../log';
import { appPlatformDisplayNames } from '../../platform';
@@ -200,7 +200,8 @@ async function maybeGetBuildAsync(
projectId: string,
paginatedQueryOptions: PaginatedQueryOptions
): Promise<BuildFragment | null> {
const simulator = flags.selectedPlatform === AppPlatform.Ios ? true : undefined;
const distributionType =
flags.selectedPlatform === AppPlatform.Ios ? DistributionType.Simulator : undefined;
if (flags.runArchiveFlags.id) {
const build = await BuildQuery.byIdAsync(graphqlClient, flags.runArchiveFlags.id);
@@ -218,9 +219,9 @@ async function maybeGetBuildAsync(
} build to run for ${await getDisplayNameForProjectIdAsync(graphqlClient, projectId)} app`,
filter: {
platform: flags.selectedPlatform,
distribution: distributionType,
status: BuildStatus.Finished,
buildProfile: flags.profile,
simulator,
},
paginatedQueryOptions,
selectPromptDisabledFunction: build => !isRunnableOnSimulatorOrEmulator(build),
@@ -234,9 +235,9 @@ async function maybeGetBuildAsync(
projectId,
filter: {
platform: flags.selectedPlatform,
distribution: distributionType,
status: BuildStatus.Finished,
buildProfile: flags.profile,
simulator,
},
});
@@ -1,4 +1,4 @@
import { getRuntimeVersionNullableAsync } from '@expo/config-plugins/build/utils/Updates';
import { getRuntimeVersionNullable } from '@expo/config-plugins/build/utils/Updates';
import { Platform } from '@expo/eas-build-job';
import { EasJsonAccessor, EasJsonUtils } from '@expo/eas-json';
import { Flags } from '@oclif/core';
@@ -116,8 +116,7 @@ export default class BuildVersionSetView extends EasCommand {
applicationIdentifier,
storeVersion: exp.version ?? '1.0.0',
buildVersion: String(version),
runtimeVersion:
(await getRuntimeVersionNullableAsync(projectDir, exp, platform)) ?? undefined,
runtimeVersion: getRuntimeVersionNullable(exp, platform) ?? undefined,
});
}
}
@@ -4,11 +4,7 @@ import { print } from 'graphql';
import gql from 'graphql-tag';
import { selectBranchOnAppAsync } from '../../branch/queries';
import {
getAlwaysTrueBranchMapping,
hasEmptyBranchMap,
hasStandardBranchMap,
} from '../../channel/branch-mapping';
import { hasEmptyBranchMap, hasStandardBranchMap } from '../../channel/branch-mapping';
import { selectChannelOnAppAsync } from '../../channel/queries';
import EasCommand from '../../commandUtils/EasCommand';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
@@ -128,7 +124,11 @@ export default class ChannelEdit extends EasCommand {
const channel = await updateChannelBranchMappingAsync(graphqlClient, {
channelId: existingChannel.id,
branchMapping: JSON.stringify(getAlwaysTrueBranchMapping(branch.id)),
// todo: move branch mapping logic to utility
branchMapping: JSON.stringify({
data: [{ branchId: branch.id, branchMappingLogic: 'true' }],
version: 0,
}),
});
if (json) {
@@ -132,7 +132,7 @@ export default class ChannelRollout extends EasCommand {
const { args, flags } = await this.parse(ChannelRollout);
const argsAndFlags = this.sanitizeArgsAndFlags({ ...flags, ...args });
const {
privateProjectConfig: { exp, projectId, projectDir },
privateProjectConfig: { exp, projectId },
loggedIn: { graphqlClient },
} = await this.getContextAsync(ChannelRollout, {
nonInteractive: argsAndFlags.nonInteractive,
@@ -141,8 +141,9 @@ export default class ChannelRollout extends EasCommand {
enableJsonOutput();
}
const app = { projectId, exp, projectDir };
const app = { projectId, exp };
const ctx = {
projectId,
nonInteractive: argsAndFlags.nonInteractive,
graphqlClient,
app,
+2 -14
View File
@@ -1,4 +1,4 @@
import { ConfigError, getProjectConfigDescription } from '@expo/config';
import { getProjectConfigDescription } from '@expo/config';
import { ExpoConfig } from '@expo/config-types';
import { Flags } from '@oclif/core';
import chalk from 'chalk';
@@ -60,19 +60,7 @@ export default class ProjectInit extends EasCommand {
projectDir: string,
modifications: Partial<ExpoConfig>
): Promise<void> {
let result;
try {
result = await createOrModifyExpoConfigAsync(projectDir, modifications);
} catch (error) {
if (error instanceof ConfigError && error.code === 'MODULE_NOT_FOUND') {
Log.warn(
'Cannot determine which native SDK version your project uses because the module `expo` is not installed.'
);
return;
} else {
throw error;
}
}
const result = await createOrModifyExpoConfigAsync(projectDir, modifications);
switch (result.type) {
case 'success':
break;
@@ -0,0 +1,30 @@
import { ExpoConfig } from '@expo/config';
import { instance, mock } from 'ts-mockito';
import { ExpoGraphqlClient } from '../../../commandUtils/context/contextUtils/createGraphqlClient';
import { ensureEASUpdateIsConfiguredAsync } from '../../../update/configure';
import { Client } from '../../../vcs/vcs';
describe(ensureEASUpdateIsConfiguredAsync, () => {
it('errors with "useClassicUpdates" set and no app.json', async () => {
const graphqlClient = instance(mock<ExpoGraphqlClient>({}));
const vcsClient = instance(mock<Client>({}));
const exp: ExpoConfig = {
name: 'test',
slug: 'test',
updates: { useClassicUpdates: true },
};
await expect(async () => {
await ensureEASUpdateIsConfiguredAsync(graphqlClient, {
exp,
projectId: 'test',
projectDir: '/tmp/test',
platform: null,
vcsClient,
});
}).rejects.toThrow(
`Your app config sets "updates.useClassicUpdates" but EAS Update does not support classic updates. Remove "useClassicUpdates" from your app config and run this command again.`
);
});
});
@@ -12,7 +12,6 @@ import {
DynamicPublicProjectConfigContextField,
} from '../../../commandUtils/context/DynamicProjectConfigContextField';
import LoggedInContextField from '../../../commandUtils/context/LoggedInContextField';
import VcsClientContextField from '../../../commandUtils/context/VcsClientContextField';
import { ExpoGraphqlClient } from '../../../commandUtils/context/contextUtils/createGraphqlClient';
import FeatureGateEnvOverrides from '../../../commandUtils/gating/FeatureGateEnvOverrides';
import FeatureGating from '../../../commandUtils/gating/FeatureGating';
@@ -22,7 +21,6 @@ import { PublishMutation } from '../../../graphql/mutations/PublishMutation';
import { AppQuery } from '../../../graphql/queries/AppQuery';
import { collectAssetsAsync, uploadAssetsAsync } from '../../../project/publish';
import { getBranchNameFromChannelNameAsync } from '../../../update/getBranchNameFromChannelNameAsync';
import { resolveVcsClient } from '../../../vcs';
const projectRoot = '/test-project';
const commandOptions = { root: projectRoot } as any;
@@ -267,9 +265,6 @@ function mockTestProject({
featureGating: new FeatureGating({}, new FeatureGateEnvOverrides()),
graphqlClient,
});
jest
.spyOn(VcsClientContextField.prototype, 'getValueAsync')
.mockResolvedValue(resolveVcsClient());
jest.mocked(AppQuery.byIdAsync).mockResolvedValue({
id: '1234',
@@ -329,7 +324,7 @@ function mockTestExport({
uniqueUploadedAssetPaths: [],
});
jest.mocked(Updates.getRuntimeVersionAsync).mockResolvedValue(runtimeVersion);
jest.mocked(Updates.getRuntimeVersion).mockReturnValue(runtimeVersion);
return { inputDir: exportDir, platforms, runtimeVersion };
}
@@ -11,7 +11,6 @@ import {
DynamicPublicProjectConfigContextField,
} from '../../../commandUtils/context/DynamicProjectConfigContextField';
import LoggedInContextField from '../../../commandUtils/context/LoggedInContextField';
import VcsClientContextField from '../../../commandUtils/context/VcsClientContextField';
import { ExpoGraphqlClient } from '../../../commandUtils/context/contextUtils/createGraphqlClient';
import FeatureGateEnvOverrides from '../../../commandUtils/gating/FeatureGateEnvOverrides';
import FeatureGating from '../../../commandUtils/gating/FeatureGating';
@@ -20,7 +19,6 @@ import { UpdateFragment } from '../../../graphql/generated';
import { PublishMutation } from '../../../graphql/mutations/PublishMutation';
import { AppQuery } from '../../../graphql/queries/AppQuery';
import { getBranchNameFromChannelNameAsync } from '../../../update/getBranchNameFromChannelNameAsync';
import { resolveVcsClient } from '../../../vcs';
import UpdateRollBackToEmbedded from '../roll-back-to-embedded';
const projectRoot = '/test-project';
@@ -86,7 +84,7 @@ describe(UpdateRollBackToEmbedded.name, () => {
mockTestProject();
const platforms = ['android', 'ios'];
const runtimeVersion = 'exposdk:47.0.0';
jest.mocked(Updates.getRuntimeVersionAsync).mockResolvedValue(runtimeVersion);
jest.mocked(Updates.getRuntimeVersion).mockReturnValue(runtimeVersion);
jest.mocked(ensureBranchExistsAsync).mockResolvedValue({
branchId: 'branch123',
@@ -108,7 +106,7 @@ describe(UpdateRollBackToEmbedded.name, () => {
const { projectId } = mockTestProject();
const platforms = ['android', 'ios'];
const runtimeVersion = 'exposdk:47.0.0';
jest.mocked(Updates.getRuntimeVersionAsync).mockResolvedValue(runtimeVersion);
jest.mocked(Updates.getRuntimeVersion).mockReturnValue(runtimeVersion);
jest.mocked(getBranchNameFromChannelNameAsync).mockResolvedValue('branchFromChannel');
jest.mocked(ensureBranchExistsAsync).mockResolvedValue({
@@ -156,7 +154,7 @@ describe(UpdateRollBackToEmbedded.name, () => {
const platforms = ['ios'];
const runtimeVersion = 'exposdk:47.0.0';
jest.mocked(Updates.getRuntimeVersionAsync).mockResolvedValue(runtimeVersion);
jest.mocked(Updates.getRuntimeVersion).mockReturnValue(runtimeVersion);
// Mock an existing branch, so we don't create a new one
jest.mocked(ensureBranchExistsAsync).mockResolvedValue({
@@ -252,9 +250,6 @@ function mockTestProject({
featureGating: new FeatureGating({}, new FeatureGateEnvOverrides()),
graphqlClient,
});
jest
.spyOn(VcsClientContextField.prototype, 'getValueAsync')
.mockResolvedValue(resolveVcsClient());
jest.mocked(AppQuery.byIdAsync).mockResolvedValue({
id: '1234',
@@ -35,6 +35,7 @@ export default class UpdateConfigure extends EasCommand {
const platform = flags.platform as RequestedPlatform;
const {
privateProjectConfig: { projectId, exp, projectDir },
loggedIn: { graphqlClient },
vcsClient,
} = await this.getContextAsync(UpdateConfigure, {
nonInteractive: flags['non-interactive'],
@@ -46,7 +47,7 @@ export default class UpdateConfigure extends EasCommand {
await vcsClient.ensureRepoExistsAsync();
await ensureEASUpdateIsConfiguredAsync({
await ensureEASUpdateIsConfiguredAsync(graphqlClient, {
exp,
projectId,
projectDir,
+20 -12
View File
@@ -4,7 +4,6 @@ import chalk from 'chalk';
import nullthrows from 'nullthrows';
import { ensureBranchExistsAsync } from '../../branch/queries';
import { ensureRepoIsCleanAsync } from '../../build/utils/repository';
import { getUpdateGroupUrl } from '../../build/utils/url';
import { ensureChannelExistsAsync } from '../../channel/queries';
import EasCommand from '../../commandUtils/EasCommand';
@@ -30,6 +29,7 @@ import {
collectAssetsAsync,
defaultPublishPlatforms,
filterExportedPlatformsByFlag,
generateEasMetadataAsync,
getBranchNameForCommandAsync,
getRequestedPlatform,
getRuntimeToPlatformMappingFromRuntimeVersions,
@@ -56,6 +56,7 @@ import { maybeWarnAboutEasOutagesAsync } from '../../utils/statuspageService';
type RawUpdateFlags = {
auto: boolean;
dev: boolean;
branch?: string;
channel?: string;
message?: string;
@@ -74,6 +75,7 @@ type RawUpdateFlags = {
type UpdateFlags = {
auto: boolean;
dev: boolean;
platform: ExpoCLIExportPlatformFlag;
branchName?: string;
channelName?: string;
@@ -134,6 +136,10 @@ export default class UpdatePublish extends EasCommand {
default: 'all',
required: false,
}),
dev: Flags.boolean({
description: 'Publish a development bundle',
default: false,
}),
auto: Flags.boolean({
description:
'Use the current git branch and commit message for the EAS branch and update message',
@@ -159,6 +165,7 @@ export default class UpdatePublish extends EasCommand {
auto: autoFlag,
platform: platformFlag,
channelName: channelNameArg,
dev,
updateMessage: updateMessageArg,
inputDir,
skipBundler,
@@ -182,9 +189,6 @@ export default class UpdatePublish extends EasCommand {
enableJsonOutput();
}
await vcsClient.ensureRepoExistsAsync();
await ensureRepoIsCleanAsync(vcsClient, nonInteractive);
const {
exp: expPossiblyWithoutEasUpdateConfigured,
projectId,
@@ -193,7 +197,7 @@ export default class UpdatePublish extends EasCommand {
await maybeWarnAboutEasOutagesAsync(graphqlClient, [StatuspageServiceName.EasUpdate]);
await ensureEASUpdateIsConfiguredAsync({
await ensureEASUpdateIsConfiguredAsync(graphqlClient, {
exp: expPossiblyWithoutEasUpdateConfigured,
platform: getRequestedPlatform(platformFlag),
projectDir,
@@ -227,7 +231,7 @@ export default class UpdatePublish extends EasCommand {
if (!skipBundler) {
const bundleSpinner = ora().start('Exporting...');
try {
await buildBundlesAsync({ projectDir, inputDir, exp, platformFlag, clearCache });
await buildBundlesAsync({ projectDir, inputDir, dev, exp, platformFlag, clearCache });
bundleSpinner.succeed('Exported bundle(s)');
} catch (e) {
bundleSpinner.fail('Export failed');
@@ -351,7 +355,7 @@ export default class UpdatePublish extends EasCommand {
Log.withInfo(
`${platformString} (maximum: ${assetLimitPerUpdateGroup} total per update). ${learnMore(
'https://expo.fyi/eas-update-asset-limits',
{ learnMoreMessage: 'Learn more about asset limits' }
{ learnMoreMessage: 'Learn more about asset limits.' }
)}`
);
} catch (e) {
@@ -359,12 +363,12 @@ export default class UpdatePublish extends EasCommand {
throw e;
}
const runtimeVersions = await getRuntimeVersionObjectAsync({
const runtimeVersions = await getRuntimeVersionObjectAsync(
exp,
platforms: realizedPlatforms,
realizedPlatforms,
projectDir,
vcsClient,
});
vcsClient
);
const runtimeToPlatformMapping =
getRuntimeToPlatformMappingFromRuntimeVersions(runtimeVersions);
@@ -465,6 +469,9 @@ export default class UpdatePublish extends EasCommand {
throw e;
}
if (!skipBundler) {
await generateEasMetadataAsync(distRoot, getUpdateJsonInfosForUpdates(newUpdates));
}
if (jsonFlag) {
printJsonOnlyOutput(getUpdateJsonInfosForUpdates(newUpdates));
} else {
@@ -540,7 +547,7 @@ export default class UpdatePublish extends EasCommand {
private sanitizeFlags(flags: RawUpdateFlags): UpdateFlags {
const nonInteractive = flags['non-interactive'] ?? false;
const { auto, branch: branchName, channel: channelName, message: updateMessage } = flags;
const { auto, branch: branchName, channel: channelName, dev, message: updateMessage } = flags;
if (nonInteractive && !auto && !(updateMessage && (branchName || channelName))) {
Errors.error(
'--branch and --message, or --channel and --message are required when updating in non-interactive mode unless --auto is specified',
@@ -569,6 +576,7 @@ export default class UpdatePublish extends EasCommand {
auto,
branchName,
channelName,
dev,
updateMessage,
inputDir: flags['input-dir'],
skipBundler: flags['skip-bundler'],
@@ -293,7 +293,12 @@ async function askUpdatesFromChannelNameAsync(
nonInteractive,
}: { projectId: string; channelName: string; json: boolean; nonInteractive: boolean }
): Promise<UpdateToRepublish[]> {
const branchName = await getBranchNameFromChannelNameAsync(graphqlClient, projectId, channelName);
const branchName = await getBranchNameFromChannelNameAsync(
graphqlClient,
projectId,
channelName,
{ json, nonInteractive, offset: 0 }
);
return await askUpdatesFromBranchNameAsync(graphqlClient, {
projectId,
@@ -148,7 +148,7 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
await maybeWarnAboutEasOutagesAsync(graphqlClient, [StatuspageServiceName.EasUpdate]);
await ensureEASUpdateIsConfiguredAsync({
await ensureEASUpdateIsConfiguredAsync(graphqlClient, {
exp: expPossiblyWithoutEasUpdateConfigured,
platform: getRequestedPlatform(platformFlag),
projectDir,
@@ -201,12 +201,12 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
const gitCommitHash = await vcsClient.getCommitHashAsync();
const isGitWorkingTreeDirty = await vcsClient.hasUncommittedChangesAsync();
const runtimeVersions = await getRuntimeVersionObjectAsync({
const runtimeVersions = await getRuntimeVersionObjectAsync(
exp,
platforms: realizedPlatforms,
realizedPlatforms,
projectDir,
vcsClient,
});
vcsClient
);
let newUpdates: UpdatePublishMutation['updateBranch']['publishUpdateGroups'];
const publishSpinner = ora('Publishing...').start();
@@ -6,7 +6,7 @@ import Log from '../../../log';
import { CredentialsContext } from '../../context';
import { AppLookupParams } from '../api/GraphqlClient';
export class AssignGoogleServiceAccountKeyForSubmissions {
export class AssignGoogleServiceAccountKey {
constructor(private app: AppLookupParams) {}
public async runAsync(
@@ -1,33 +0,0 @@
import {
CommonAndroidAppCredentialsFragment,
GoogleServiceAccountKeyFragment,
} from '../../../graphql/generated';
import Log from '../../../log';
import { CredentialsContext } from '../../context';
import { AppLookupParams } from '../api/GraphqlClient';
export class AssignGoogleServiceAccountKeyForFcmV1 {
constructor(private app: AppLookupParams) {}
public async runAsync(
ctx: CredentialsContext,
googleServiceAccountKey: GoogleServiceAccountKeyFragment
): Promise<CommonAndroidAppCredentialsFragment> {
const appCredentials =
await ctx.android.createOrGetExistingAndroidAppCredentialsWithBuildCredentialsAsync(
ctx.graphqlClient,
this.app
);
const updatedAppCredentials = await ctx.android.updateAndroidAppCredentialsAsync(
ctx.graphqlClient,
appCredentials,
{
googleServiceAccountKeyForFcmV1Id: googleServiceAccountKey.id,
}
);
Log.succeed(
`Google Service Account Key assigned to ${this.app.androidApplicationIdentifier} for FCM V1`
);
return updatedAppCredentials;
}
}
@@ -46,7 +46,7 @@ export class CreateGoogleServiceAccountKey {
Log.log(
`${chalk.bold(
'A Google Service Account JSON key is required for uploading your app to Google Play Store, and for sending Android Notifications via FCM V1.'
'A Google Service Account JSON key is required to upload your app to Google Play Store'
)}.\n` +
`If you're not sure what this is or how to create one, ${learnMore(
'https://expo.fyi/creating-google-service-account',
@@ -1,6 +1,6 @@
import nullthrows from 'nullthrows';
import { AssignGoogleServiceAccountKeyForSubmissions } from './AssignGoogleServiceAccountKeyForSubmissions';
import { AssignGoogleServiceAccountKey } from './AssignGoogleServiceAccountKey';
import { CreateGoogleServiceAccountKey } from './CreateGoogleServiceAccountKey';
import { UseExistingGoogleServiceAccountKey } from './UseExistingGoogleServiceAccountKey';
import {
@@ -13,7 +13,7 @@ import { CredentialsContext } from '../../context';
import { MissingCredentialsNonInteractiveError } from '../../errors';
import { AppLookupParams } from '../api/GraphqlClient';
export class SetUpGoogleServiceAccountKeyForSubmissions {
export class SetUpGoogleServiceAccountKey {
constructor(private app: AppLookupParams) {}
public async runAsync(ctx: CredentialsContext): Promise<CommonAndroidAppCredentialsFragment> {
@@ -46,10 +46,7 @@ export class SetUpGoogleServiceAccountKeyForSubmissions {
} else {
googleServiceAccountKey = await this.createOrUseExistingKeyAsync(ctx);
}
return await new AssignGoogleServiceAccountKeyForSubmissions(this.app).runAsync(
ctx,
googleServiceAccountKey
);
return await new AssignGoogleServiceAccountKey(this.app).runAsync(ctx, googleServiceAccountKey);
}
private async isGoogleServiceAccountKeySetupAsync(ctx: CredentialsContext): Promise<boolean> {
@@ -1,87 +0,0 @@
import nullthrows from 'nullthrows';
import { AssignGoogleServiceAccountKeyForFcmV1 } from './AssignGoogleServiceAccountKeyForFcmV1';
import { CreateGoogleServiceAccountKey } from './CreateGoogleServiceAccountKey';
import { UseExistingGoogleServiceAccountKey } from './UseExistingGoogleServiceAccountKey';
import {
CommonAndroidAppCredentialsFragment,
GoogleServiceAccountKeyFragment,
} from '../../../graphql/generated';
import Log from '../../../log';
import { promptAsync } from '../../../prompts';
import { CredentialsContext } from '../../context';
import { MissingCredentialsNonInteractiveError } from '../../errors';
import { AppLookupParams } from '../api/GraphqlClient';
export class SetUpGoogleServiceAccountKeyForFcmV1 {
constructor(private app: AppLookupParams) {}
public async runAsync(ctx: CredentialsContext): Promise<CommonAndroidAppCredentialsFragment> {
const isKeySetup = await this.isGoogleServiceAccountKeySetupAsync(ctx);
if (isKeySetup) {
Log.succeed('Google Service Account Key for FCM V1 already set up.');
return nullthrows(
await ctx.android.getAndroidAppCredentialsWithCommonFieldsAsync(
ctx.graphqlClient,
this.app
),
'androidAppCredentials cannot be null if google service account key is already set up'
);
}
if (ctx.nonInteractive) {
throw new MissingCredentialsNonInteractiveError(
'Google Service Account Keys cannot be set up in --non-interactive mode.'
);
}
const keysForAccount = await ctx.android.getGoogleServiceAccountKeysForAccountAsync(
ctx.graphqlClient,
this.app.account
);
let googleServiceAccountKey = null;
if (keysForAccount.length === 0) {
googleServiceAccountKey = await new CreateGoogleServiceAccountKey(this.app.account).runAsync(
ctx
);
} else {
googleServiceAccountKey = await this.createOrUseExistingKeyAsync(ctx);
}
return await new AssignGoogleServiceAccountKeyForFcmV1(this.app).runAsync(
ctx,
googleServiceAccountKey
);
}
private async isGoogleServiceAccountKeySetupAsync(ctx: CredentialsContext): Promise<boolean> {
const appCredentials = await ctx.android.getAndroidAppCredentialsWithCommonFieldsAsync(
ctx.graphqlClient,
this.app
);
return !!appCredentials?.googleServiceAccountKeyForFcmV1;
}
private async createOrUseExistingKeyAsync(
ctx: CredentialsContext
): Promise<GoogleServiceAccountKeyFragment> {
const { action } = await promptAsync({
type: 'select',
name: 'action',
message: 'Select the Google Service Account Key to use for FCM V1:',
choices: [
{
title: '[Choose an existing key]',
value: 'CHOOSE_EXISTING',
},
{ title: '[Upload a new service account key]', value: 'GENERATE' },
],
});
if (action === 'GENERATE') {
return await new CreateGoogleServiceAccountKey(this.app.account).runAsync(ctx);
}
return (
(await new UseExistingGoogleServiceAccountKey(this.app.account).runAsync(ctx)) ??
(await this.createOrUseExistingKeyAsync(ctx))
);
}
}
@@ -2,12 +2,12 @@ import { AppQuery } from '../../../../graphql/queries/AppQuery';
import { testGoogleServiceAccountKeyFragment } from '../../../__tests__/fixtures-android';
import { testAppQueryByIdResponse } from '../../../__tests__/fixtures-constants';
import { createCtxMock } from '../../../__tests__/fixtures-context';
import { AssignGoogleServiceAccountKeyForSubmissions } from '../AssignGoogleServiceAccountKeyForSubmissions';
import { AssignGoogleServiceAccountKey } from '../AssignGoogleServiceAccountKey';
import { getAppLookupParamsFromContextAsync } from '../BuildCredentialsUtils';
jest.mock('../../../../graphql/queries/AppQuery');
describe(AssignGoogleServiceAccountKeyForSubmissions, () => {
describe(AssignGoogleServiceAccountKey, () => {
beforeEach(() => {
jest.mocked(AppQuery.byIdAsync).mockResolvedValue(testAppQueryByIdResponse);
});
@@ -16,9 +16,7 @@ describe(AssignGoogleServiceAccountKeyForSubmissions, () => {
nonInteractive: false,
});
const appLookupParams = await getAppLookupParamsFromContextAsync(ctx);
const assignGoogleServiceAccountKeyAction = new AssignGoogleServiceAccountKeyForSubmissions(
appLookupParams
);
const assignGoogleServiceAccountKeyAction = new AssignGoogleServiceAccountKey(appLookupParams);
await assignGoogleServiceAccountKeyAction.runAsync(ctx, testGoogleServiceAccountKeyFragment);
// expect app credentials to be fetched/created, then updated
@@ -32,9 +30,7 @@ describe(AssignGoogleServiceAccountKeyForSubmissions, () => {
nonInteractive: true,
});
const appLookupParams = await getAppLookupParamsFromContextAsync(ctx);
const assignGoogleServiceAccountKeyAction = new AssignGoogleServiceAccountKeyForSubmissions(
appLookupParams
);
const assignGoogleServiceAccountKeyAction = new AssignGoogleServiceAccountKey(appLookupParams);
// dont fail if users are running in non-interactive mode
await expect(
@@ -11,7 +11,7 @@ import { testAppQueryByIdResponse } from '../../../__tests__/fixtures-constants'
import { createCtxMock } from '../../../__tests__/fixtures-context';
import { MissingCredentialsNonInteractiveError } from '../../../errors';
import { getAppLookupParamsFromContextAsync } from '../BuildCredentialsUtils';
import { SetUpGoogleServiceAccountKeyForSubmissions } from '../SetUpGoogleServiceAccountKeyForSubmissions';
import { SetUpGoogleServiceAccountKey } from '../SetUpGoogleServiceAccountKey';
jest.mock('../../../../prompts');
jest.mock('fs');
@@ -24,7 +24,7 @@ beforeEach(() => {
vol.reset();
});
describe(SetUpGoogleServiceAccountKeyForSubmissions, () => {
describe(SetUpGoogleServiceAccountKey, () => {
beforeEach(() => {
jest.mocked(AppQuery.byIdAsync).mockResolvedValue(testAppQueryByIdResponse);
});
@@ -39,9 +39,7 @@ describe(SetUpGoogleServiceAccountKeyForSubmissions, () => {
},
});
const appLookupParams = await getAppLookupParamsFromContextAsync(ctx);
const setupGoogleServiceAccountKeyAction = new SetUpGoogleServiceAccountKeyForSubmissions(
appLookupParams
);
const setupGoogleServiceAccountKeyAction = new SetUpGoogleServiceAccountKey(appLookupParams);
await setupGoogleServiceAccountKeyAction.runAsync(ctx);
expect(ctx.android.createGoogleServiceAccountKeyAsync).not.toHaveBeenCalled();
@@ -64,9 +62,7 @@ describe(SetUpGoogleServiceAccountKeyForSubmissions, () => {
},
});
const appLookupParams = await getAppLookupParamsFromContextAsync(ctx);
const setupGoogleServiceAccountKeyAction = new SetUpGoogleServiceAccountKeyForSubmissions(
appLookupParams
);
const setupGoogleServiceAccountKeyAction = new SetUpGoogleServiceAccountKey(appLookupParams);
await setupGoogleServiceAccountKeyAction.runAsync(ctx);
expect(ctx.android.createGoogleServiceAccountKeyAsync).toHaveBeenCalledTimes(1);
@@ -77,9 +73,7 @@ describe(SetUpGoogleServiceAccountKeyForSubmissions, () => {
nonInteractive: true,
});
const appLookupParams = await getAppLookupParamsFromContextAsync(ctx);
const setupGoogleServiceAccountKeyAction = new SetUpGoogleServiceAccountKeyForSubmissions(
appLookupParams
);
const setupGoogleServiceAccountKeyAction = new SetUpGoogleServiceAccountKey(appLookupParams);
await expect(setupGoogleServiceAccountKeyAction.runAsync(ctx)).rejects.toThrowError(
MissingCredentialsNonInteractiveError
);
@@ -106,11 +106,9 @@ export async function updateAndroidAppCredentialsAsync(
{
androidFcmId,
googleServiceAccountKeyForSubmissionsId,
googleServiceAccountKeyForFcmV1Id,
}: {
androidFcmId?: string;
googleServiceAccountKeyForSubmissionsId?: string;
googleServiceAccountKeyForFcmV1Id?: string;
}
): Promise<CommonAndroidAppCredentialsFragment> {
let updatedAppCredentials = appCredentials;
@@ -129,14 +127,6 @@ export async function updateAndroidAppCredentialsAsync(
googleServiceAccountKeyForSubmissionsId
);
}
if (googleServiceAccountKeyForFcmV1Id) {
updatedAppCredentials =
await AndroidAppCredentialsMutation.setGoogleServiceAccountKeyForFcmV1Async(
graphqlClient,
appCredentials.id,
googleServiceAccountKeyForFcmV1Id
);
}
return updatedAppCredentials;
}
@@ -8,7 +8,6 @@ import {
CommonAndroidAppCredentialsFragment,
CreateAndroidAppCredentialsMutation,
SetFcmMutation,
SetGoogleServiceAccountKeyForFcmV1Mutation,
SetGoogleServiceAccountKeyForSubmissionsMutation,
} from '../../../../../graphql/generated';
import { CommonAndroidAppCredentialsFragmentNode } from '../../../../../graphql/types/credentials/AndroidAppCredentials';
@@ -125,42 +124,4 @@ export const AndroidAppCredentialsMutation = {
);
return data.androidAppCredentials.setGoogleServiceAccountKeyForSubmissions;
},
async setGoogleServiceAccountKeyForFcmV1Async(
graphqlClient: ExpoGraphqlClient,
androidAppCredentialsId: string,
googleServiceAccountKeyId: string
): Promise<CommonAndroidAppCredentialsFragment> {
const data = await withErrorHandlingAsync(
graphqlClient
.mutation<SetGoogleServiceAccountKeyForFcmV1Mutation>(
gql`
mutation SetGoogleServiceAccountKeyForFcmV1Mutation(
$androidAppCredentialsId: ID!
$googleServiceAccountKeyId: ID!
) {
androidAppCredentials {
setGoogleServiceAccountKeyForFcmV1(
id: $androidAppCredentialsId
googleServiceAccountKeyId: $googleServiceAccountKeyId
) {
id
...CommonAndroidAppCredentialsFragment
}
}
}
${print(CommonAndroidAppCredentialsFragmentNode)}
`,
{
androidAppCredentialsId,
googleServiceAccountKeyId,
}
)
.toPromise()
);
assert(
data.androidAppCredentials.setGoogleServiceAccountKeyForFcmV1,
'GraphQL: `setGoogleServiceAccountKeyForFcmV1` not defined in server response'
);
return data.androidAppCredentials.setGoogleServiceAccountKeyForFcmV1;
},
};
@@ -3,8 +3,8 @@
exports[`print credentials prints the AndroidAppCredentials fragment 1`] = `
"Android Credentials
Project testApp
Application Identifier test.com.appPush Notifications (FCM Legacy) Key abcd...efgh
Updated 0 second agoPush Notifications (FCM V1): Google Service Account Key For FCM V1 None assigned yetSubmissions: Google Service Account Key for Play Store Submissions Project ID sdf.sdf.sdf
Application Identifier test.com.appPush Notifications (FCM) Key abcd...efgh
Updated 0 second agoGoogle Service Account Key For Submissions Project ID sdf.sdf.sdf
Client Email [email protected]
Client ID test-client-identifier
Private Key ID test-private-key-identifier
@@ -13,11 +13,7 @@ import { getAppLookupParamsFromContextAsync } from '../../actions/BuildCredentia
import { displayAndroidAppCredentials } from '../printCredentials';
jest.mock('../../../../log');
jest.mock('chalk', () => ({
bold: jest.fn(log => log),
cyan: { bold: jest.fn(log => log) },
dim: jest.fn(log => log),
}));
jest.mock('chalk', () => ({ bold: jest.fn(log => log), cyan: { bold: jest.fn(log => log) } }));
jest.mock('../../../../graphql/queries/AppQuery');
mockdate.set(testLegacyAndroidFcmFragment.updatedAt);
@@ -96,7 +96,7 @@ export async function detectGoogleServiceAccountKeyPathAsync(
): Promise<string | null> {
const foundFilePaths = await glob('**/*.json', {
cwd: projectDir,
ignore: ['app.json', 'package*.json', 'tsconfig.json', 'node_modules', 'google-services.json'],
ignore: ['app.json', 'package*.json', 'tsconfig.json', 'node_modules'],
});
const googleServiceFiles = foundFilePaths
@@ -29,7 +29,7 @@ export function displayEmptyAndroidCredentials(appLookupParams: AppLookupParams)
function displayAndroidFcmCredentials(appCredentials: CommonAndroidAppCredentialsFragment): void {
const maybeFcm = appCredentials.androidFcm;
Log.log(
formatFields([{ label: 'Push Notifications (FCM Legacy)', value: '' }], {
formatFields([{ label: 'Push Notifications (FCM)', value: '' }], {
labelFormat: chalk.cyan.bold,
})
);
@@ -60,43 +60,9 @@ function displayGoogleServiceAccountKeyForSubmissions(
): void {
const maybeGsaKey = appCredentials.googleServiceAccountKeyForSubmissions;
Log.log(
formatFields(
[{ label: 'Submissions: Google Service Account Key for Play Store Submissions', value: '' }],
{
labelFormat: chalk.cyan.bold,
}
)
);
if (!maybeGsaKey) {
Log.log(formatFields([{ label: '', value: 'None assigned yet' }]));
Log.newLine();
return;
}
const { projectIdentifier, privateKeyIdentifier, clientEmail, clientIdentifier, updatedAt } =
maybeGsaKey;
const fields = [
{ label: 'Project ID', value: projectIdentifier },
{ label: 'Client Email', value: clientEmail },
{ label: 'Client ID', value: clientIdentifier },
{ label: 'Private Key ID', value: privateKeyIdentifier },
{ label: 'Updated', value: `${fromNow(new Date(updatedAt))} ago` },
];
Log.log(formatFields(fields, { labelFormat: chalk.cyan.bold }));
Log.newLine();
}
function displayGoogleServiceAccountKeyForFcmV1(
appCredentials: CommonAndroidAppCredentialsFragment
): void {
const maybeGsaKey = appCredentials.googleServiceAccountKeyForFcmV1;
Log.log(
formatFields(
[{ label: 'Push Notifications (FCM V1): Google Service Account Key For FCM V1', value: '' }],
{
labelFormat: chalk.cyan.bold,
}
)
formatFields([{ label: 'Google Service Account Key For Submissions', value: '' }], {
labelFormat: chalk.cyan.bold,
})
);
if (!maybeGsaKey) {
Log.log(formatFields([{ label: '', value: 'None assigned yet' }]));
@@ -121,7 +87,6 @@ function displayEASAndroidAppCredentials(
appCredentials: CommonAndroidAppCredentialsFragment
): void {
displayAndroidFcmCredentials(appCredentials);
displayGoogleServiceAccountKeyForFcmV1(appCredentials);
displayGoogleServiceAccountKeyForSubmissions(appCredentials);
const sortedBuildCredentialsList = sortBuildCredentials(
appCredentials.androidAppBuildCredentialsList
@@ -1,5 +1,6 @@
import { AppStoreApiKeyPurpose, provideOrGenerateAscApiKeyAsync } from './AscApiKeyUtils';
import { AccountFragment, AppStoreConnectApiKeyFragment } from '../../../graphql/generated';
import Log from '../../../log';
import { CredentialsContext } from '../../context';
export class CreateAscApiKey {
@@ -14,6 +15,8 @@ export class CreateAscApiKey {
}
const ascApiKey = await provideOrGenerateAscApiKeyAsync(ctx, purpose);
return await ctx.ios.createAscApiKeyAsync(ctx.graphqlClient, this.account, ascApiKey);
const result = await ctx.ios.createAscApiKeyAsync(ctx.graphqlClient, this.account, ascApiKey);
Log.succeed('Created App Store Connect API Key');
return result;
}
}
@@ -13,9 +13,7 @@ export enum Scope {
export enum AndroidActionType {
ManageBuildCredentials,
ManageFcm,
ManageGoogleServiceAccountKeyForSubmissions,
ManageGoogleServiceAccount,
ManageGoogleServiceAccountKeyForFcmV1,
ManageGoogleServiceAccountKey,
ManageCredentialsJson,
GoBackToCaller,
GoBackToHighLevelActions,
@@ -26,13 +24,9 @@ export enum AndroidActionType {
CreateFcm,
RemoveFcm,
CreateGsaKey,
UseExistingGsaKeyForSubmissions,
UseExistingGsaKey,
RemoveGsaKey,
SetUpGsaKeyForSubmissions,
CreateGsaKeyForFcmV1,
UseExistingGsaKeyForFcmV1,
RemoveGsaKeyForFcmV1,
SetUpGsaKeyForFcmV1,
SetUpGsaKey,
UpdateCredentialsJson,
SetUpBuildCredentialsFromCredentialsJson,
}
@@ -7,13 +7,13 @@ export const highLevelActions: ActionInfo[] = [
scope: Scope.Manager,
},
{
value: AndroidActionType.ManageGoogleServiceAccount,
title: 'Google Service Account',
value: AndroidActionType.ManageFcm,
title: 'Push Notifications: Manage your FCM API Key',
scope: Scope.Manager,
},
{
value: AndroidActionType.ManageFcm,
title: 'Push Notifications (Legacy): Manage your FCM (Legacy) API Key',
value: AndroidActionType.ManageGoogleServiceAccountKey,
title: 'Google Service Account: Manage your Service Account Key',
scope: Scope.Manager,
},
{
@@ -92,58 +92,22 @@ export const fcmActions: ActionInfo[] = [
},
];
export const gsaKeyActionsForFcmV1: ActionInfo[] = [
export const gsaKeyActions: ActionInfo[] = [
{
value: AndroidActionType.SetUpGsaKeyForFcmV1,
title: 'Set up a Google Service Account Key for Push Notifications (FCM V1)',
value: AndroidActionType.SetUpGsaKey,
title: 'Set up a Google Service Account Key',
scope: Scope.Project,
},
{
value: AndroidActionType.UseExistingGsaKeyForFcmV1,
title: 'Select an existing Google Service Account Key for Push Notifications (FCM V1)',
scope: Scope.Project,
},
{
value: AndroidActionType.GoBackToHighLevelActions,
title: 'Go back',
scope: Scope.Manager,
},
];
export const gsaKeyActionsForSubmissions: ActionInfo[] = [
{
value: AndroidActionType.SetUpGsaKeyForSubmissions,
title: 'Set up a Google Service Account Key for Play Store Submissions',
scope: Scope.Project,
},
{
value: AndroidActionType.UseExistingGsaKeyForSubmissions,
title: 'Select an existing Google Service Account Key for Play Store Submissions',
scope: Scope.Project,
},
{
value: AndroidActionType.GoBackToHighLevelActions,
title: 'Go back',
scope: Scope.Manager,
},
];
export const gsaActions: ActionInfo[] = [
{
value: AndroidActionType.ManageGoogleServiceAccountKeyForSubmissions,
title: 'Manage your Google Service Account Key for Play Store Submissions',
scope: Scope.Manager,
},
{
value: AndroidActionType.ManageGoogleServiceAccountKeyForFcmV1,
title: 'Manage your Google Service Account Key for Push Notifications (FCM V1)',
scope: Scope.Manager,
},
{
value: AndroidActionType.CreateGsaKey,
title: 'Upload a Google Service Account Key',
scope: Scope.Project,
},
{
value: AndroidActionType.UseExistingGsaKey,
title: 'Use an existing Google Service Account Key',
scope: Scope.Project,
},
{
value: AndroidActionType.RemoveGsaKey,
title: 'Delete a Google Service Account Key',
@@ -7,9 +7,7 @@ import {
buildCredentialsActions,
credentialsJsonActions,
fcmActions,
gsaActions,
gsaKeyActionsForFcmV1,
gsaKeyActionsForSubmissions,
gsaKeyActions,
highLevelActions,
} from './AndroidActions';
import { CreateAndroidBuildCredentials } from './CreateAndroidBuildCredentials';
@@ -21,8 +19,7 @@ import Log, { learnMore } from '../../log';
import { GradleBuildContext, resolveGradleBuildContextAsync } from '../../project/android/gradle';
import { promptAsync } from '../../prompts';
import { AssignFcm } from '../android/actions/AssignFcm';
import { AssignGoogleServiceAccountKeyForFcmV1 } from '../android/actions/AssignGoogleServiceAccountKeyForFcmV1';
import { AssignGoogleServiceAccountKeyForSubmissions } from '../android/actions/AssignGoogleServiceAccountKeyForSubmissions';
import { AssignGoogleServiceAccountKey } from '../android/actions/AssignGoogleServiceAccountKey';
import {
canCopyLegacyCredentialsAsync,
getAppLookupParamsFromContextAsync,
@@ -35,8 +32,7 @@ import { RemoveFcm } from '../android/actions/RemoveFcm';
import { SelectAndRemoveGoogleServiceAccountKey } from '../android/actions/RemoveGoogleServiceAccountKey';
import { RemoveKeystore } from '../android/actions/RemoveKeystore';
import { SetUpBuildCredentialsFromCredentialsJson } from '../android/actions/SetUpBuildCredentialsFromCredentialsJson';
import { SetUpGoogleServiceAccountKeyForFcmV1 } from '../android/actions/SetUpGoogleServiceAccountKeyForFcmV1';
import { SetUpGoogleServiceAccountKeyForSubmissions } from '../android/actions/SetUpGoogleServiceAccountKeyForSubmissions';
import { SetUpGoogleServiceAccountKey } from '../android/actions/SetUpGoogleServiceAccountKey';
import { UpdateCredentialsJson } from '../android/actions/UpdateCredentialsJson';
import { UseExistingGoogleServiceAccountKey } from '../android/actions/UseExistingGoogleServiceAccountKey';
import {
@@ -124,16 +120,8 @@ export class ManageAndroid {
} else if (chosenAction === AndroidActionType.ManageFcm) {
currentActions = fcmActions;
continue;
} else if (chosenAction === AndroidActionType.ManageGoogleServiceAccount) {
currentActions = gsaActions;
continue;
} else if (
chosenAction === AndroidActionType.ManageGoogleServiceAccountKeyForSubmissions
) {
currentActions = gsaKeyActionsForSubmissions;
continue;
} else if (chosenAction === AndroidActionType.ManageGoogleServiceAccountKeyForFcmV1) {
currentActions = gsaKeyActionsForFcmV1;
} else if (chosenAction === AndroidActionType.ManageGoogleServiceAccountKey) {
currentActions = gsaKeyActions;
continue;
} else if (chosenAction === AndroidActionType.ManageCredentialsJson) {
currentActions = credentialsJsonActions;
@@ -205,31 +193,20 @@ export class ManageAndroid {
await new AssignFcm(appLookupParams).runAsync(ctx, fcm);
} else if (action === AndroidActionType.RemoveFcm) {
await new RemoveFcm(appLookupParams).runAsync(ctx);
} else if (action === AndroidActionType.SetUpGsaKeyForSubmissions) {
await new SetUpGoogleServiceAccountKeyForSubmissions(appLookupParams).runAsync(ctx);
} else if (action === AndroidActionType.UseExistingGsaKeyForSubmissions) {
const gsaKey = await new UseExistingGoogleServiceAccountKey(appLookupParams.account).runAsync(
ctx
);
if (gsaKey) {
await new AssignGoogleServiceAccountKeyForSubmissions(appLookupParams).runAsync(
ctx,
gsaKey
);
}
} else if (action === AndroidActionType.SetUpGsaKeyForFcmV1) {
await new SetUpGoogleServiceAccountKeyForFcmV1(appLookupParams).runAsync(ctx);
} else if (action === AndroidActionType.UseExistingGsaKeyForFcmV1) {
const gsaKey = await new UseExistingGoogleServiceAccountKey(appLookupParams.account).runAsync(
ctx
);
if (gsaKey) {
await new AssignGoogleServiceAccountKeyForFcmV1(appLookupParams).runAsync(ctx, gsaKey);
}
} else if (action === AndroidActionType.CreateGsaKey) {
await new CreateGoogleServiceAccountKey(appLookupParams.account).runAsync(ctx);
const gsaKey = await new CreateGoogleServiceAccountKey(appLookupParams.account).runAsync(ctx);
await new AssignGoogleServiceAccountKey(appLookupParams).runAsync(ctx, gsaKey);
} else if (action === AndroidActionType.UseExistingGsaKey) {
const gsaKey = await new UseExistingGoogleServiceAccountKey(appLookupParams.account).runAsync(
ctx
);
if (gsaKey) {
await new AssignGoogleServiceAccountKey(appLookupParams).runAsync(ctx, gsaKey);
}
} else if (action === AndroidActionType.RemoveGsaKey) {
await new SelectAndRemoveGoogleServiceAccountKey(appLookupParams.account).runAsync(ctx);
} else if (action === AndroidActionType.SetUpGsaKey) {
await new SetUpGoogleServiceAccountKey(appLookupParams).runAsync(ctx);
} else if (action === AndroidActionType.UpdateCredentialsJson) {
const buildCredentials = await new SelectExistingAndroidBuildCredentials(
appLookupParams
@@ -5,6 +5,6 @@ export function createCtxMock(options: { nonInteractive?: boolean } = {}): EASUp
return {
graphqlClient: jest.fn() as any,
nonInteractive: options.nonInteractive ?? false,
app: { exp: testAppJson, projectId: 'test-project-id', projectDir: '/' },
app: { exp: testAppJson, projectId: 'test-project-id' },
};
}
+1 -1
View File
@@ -5,7 +5,7 @@ import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGr
export type EASUpdateContext = {
graphqlClient: ExpoGraphqlClient;
nonInteractive: boolean;
app: { exp: ExpoConfig; projectId: string; projectDir: string };
app: { exp: ExpoConfig; projectId: string };
};
export interface EASUpdateAction<T = any> {
+14 -55
View File
@@ -759,7 +759,6 @@ export type AndroidAppCredentials = {
androidFcm?: Maybe<AndroidFcm>;
app: App;
applicationIdentifier?: Maybe<Scalars['String']['output']>;
googleServiceAccountKeyForFcmV1?: Maybe<GoogleServiceAccountKey>;
googleServiceAccountKeyForSubmissions?: Maybe<GoogleServiceAccountKey>;
id: Scalars['ID']['output'];
isLegacy: Scalars['Boolean']['output'];
@@ -772,7 +771,6 @@ export type AndroidAppCredentialsFilter = {
export type AndroidAppCredentialsInput = {
fcmId?: InputMaybe<Scalars['ID']['input']>;
googleServiceAccountKeyForFcmV1Id?: InputMaybe<Scalars['ID']['input']>;
googleServiceAccountKeyForSubmissionsId?: InputMaybe<Scalars['ID']['input']>;
};
@@ -780,17 +778,10 @@ export type AndroidAppCredentialsMutation = {
__typename?: 'AndroidAppCredentialsMutation';
/** Create a set of credentials for an Android app */
createAndroidAppCredentials: AndroidAppCredentials;
/**
* Create a GoogleServiceAccountKeyEntity to store credential and
* connect it with an edge from AndroidAppCredential
*/
createFcmV1Credential: AndroidAppCredentials;
/** Delete a set of credentials for an Android app */
deleteAndroidAppCredentials: DeleteAndroidAppCredentialsResult;
/** Set the FCM push key to be used in an Android app */
setFcm: AndroidAppCredentials;
/** Set the Google Service Account Key to be used for Firebase Cloud Messaging V1 */
setGoogleServiceAccountKeyForFcmV1: AndroidAppCredentials;
/** Set the Google Service Account Key to be used for submitting an Android app */
setGoogleServiceAccountKeyForSubmissions: AndroidAppCredentials;
};
@@ -803,13 +794,6 @@ export type AndroidAppCredentialsMutationCreateAndroidAppCredentialsArgs = {
};
export type AndroidAppCredentialsMutationCreateFcmV1CredentialArgs = {
accountId: Scalars['ID']['input'];
androidAppCredentialsId: Scalars['String']['input'];
credential: Scalars['String']['input'];
};
export type AndroidAppCredentialsMutationDeleteAndroidAppCredentialsArgs = {
id: Scalars['ID']['input'];
};
@@ -821,12 +805,6 @@ export type AndroidAppCredentialsMutationSetFcmArgs = {
};
export type AndroidAppCredentialsMutationSetGoogleServiceAccountKeyForFcmV1Args = {
googleServiceAccountKeyId: Scalars['ID']['input'];
id: Scalars['ID']['input'];
};
export type AndroidAppCredentialsMutationSetGoogleServiceAccountKeyForSubmissionsArgs = {
googleServiceAccountKeyId: Scalars['ID']['input'];
id: Scalars['ID']['input'];
@@ -2139,7 +2117,6 @@ export type Build = ActivityTimelineProjectActivity & BuildOrBuildJob & {
/** @deprecated User type is deprecated */
initiatingUser?: Maybe<User>;
iosEnterpriseProvisioning?: Maybe<BuildIosEnterpriseProvisioning>;
isForIosSimulator: Scalars['Boolean']['output'];
isGitWorkingTreeDirty?: Maybe<Scalars['Boolean']['output']>;
isWaived: Scalars['Boolean']['output'];
logFiles: Array<Scalars['String']['output']>;
@@ -2305,7 +2282,6 @@ export type BuildFilter = {
platform?: InputMaybe<AppPlatform>;
runtimeVersion?: InputMaybe<Scalars['String']['input']>;
sdkVersion?: InputMaybe<Scalars['String']['input']>;
simulator?: InputMaybe<Scalars['Boolean']['input']>;
status?: InputMaybe<BuildStatus>;
};
@@ -2315,7 +2291,6 @@ export type BuildFilterInput = {
distributions?: InputMaybe<Array<DistributionType>>;
platforms?: InputMaybe<Array<AppPlatform>>;
releaseChannel?: InputMaybe<Scalars['String']['input']>;
simulator?: InputMaybe<Scalars['Boolean']['input']>;
};
export enum BuildIosEnterpriseProvisioning {
@@ -2433,7 +2408,6 @@ export type BuildMetadataInput = {
runtimeVersion?: InputMaybe<Scalars['String']['input']>;
sdkVersion?: InputMaybe<Scalars['String']['input']>;
selectedImage?: InputMaybe<Scalars['String']['input']>;
simulator?: InputMaybe<Scalars['Boolean']['input']>;
trackingContext?: InputMaybe<Scalars['JSONObject']['input']>;
username?: InputMaybe<Scalars['String']['input']>;
workflow?: InputMaybe<BuildWorkflow>;
@@ -2614,7 +2588,6 @@ export type BuildPublicData = {
artifacts: PublicArtifacts;
distribution?: Maybe<DistributionType>;
id: Scalars['ID']['output'];
isForIosSimulator: Scalars['Boolean']['output'];
platform: AppPlatform;
project: ProjectPublicData;
status: BuildStatus;
@@ -2818,7 +2791,6 @@ export type CreateGitHubBuildTriggerInput = {
platform: AppPlatform;
/** A branch or tag name, or a wildcard pattern where the code change originates from. For example, `main` or `release/*`. */
sourcePattern: Scalars['String']['input'];
submitProfile?: InputMaybe<Scalars['String']['input']>;
/** A branch name or a wildcard pattern that the pull request targets. For example, `main` or `release/*`. */
targetPattern?: InputMaybe<Scalars['String']['input']>;
type: GitHubBuildTriggerType;
@@ -3399,7 +3371,6 @@ export type GitHubBuildTrigger = {
lastRunStatus?: Maybe<GitHubBuildTriggerRunStatus>;
platform: AppPlatform;
sourcePattern: Scalars['String']['output'];
submitProfile?: Maybe<Scalars['String']['output']>;
targetPattern?: Maybe<Scalars['String']['output']>;
type: GitHubBuildTriggerType;
updatedAt: Scalars['DateTime']['output'];
@@ -3968,7 +3939,6 @@ export enum MailchimpAudience {
export enum MailchimpTag {
DevClientUsers = 'DEV_CLIENT_USERS',
DidSubscribeToEasAtLeastOnce = 'DID_SUBSCRIBE_TO_EAS_AT_LEAST_ONCE',
EasMasterList = 'EAS_MASTER_LIST',
NewsletterSignupList = 'NEWSLETTER_SIGNUP_LIST'
}
@@ -4136,11 +4106,9 @@ export type Notification = {
export enum NotificationEvent {
BuildComplete = 'BUILD_COMPLETE',
BuildErrored = 'BUILD_ERRORED',
BuildLimitThresholdExceeded = 'BUILD_LIMIT_THRESHOLD_EXCEEDED',
BuildPlanCreditThresholdExceeded = 'BUILD_PLAN_CREDIT_THRESHOLD_EXCEEDED',
SubmissionComplete = 'SUBMISSION_COMPLETE',
SubmissionErrored = 'SUBMISSION_ERRORED',
Test = 'TEST'
}
@@ -5366,7 +5334,6 @@ export type UpdateGitHubBuildTriggerInput = {
isActive: Scalars['Boolean']['input'];
platform: AppPlatform;
sourcePattern: Scalars['String']['input'];
submitProfile?: InputMaybe<Scalars['String']['input']>;
targetPattern?: InputMaybe<Scalars['String']['input']>;
type: GitHubBuildTriggerType;
};
@@ -6143,7 +6110,7 @@ export type CreateAndroidAppCredentialsMutationVariables = Exact<{
}>;
export type CreateAndroidAppCredentialsMutation = { __typename?: 'RootMutation', androidAppCredentials: { __typename?: 'AndroidAppCredentialsMutation', createAndroidAppCredentials: { __typename?: 'AndroidAppCredentials', id: string, applicationIdentifier?: string | null, isLegacy: boolean, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, androidFcm?: { __typename?: 'AndroidFcm', id: string, credential: any, version: AndroidFcmVersion, createdAt: any, updatedAt: any, snippet: { __typename?: 'FcmSnippetLegacy', firstFourCharacters: string, lastFourCharacters: string } | { __typename?: 'FcmSnippetV1', projectId: string, keyId: string, serviceAccountEmail: string, clientId?: string | null } } | null, googleServiceAccountKeyForFcmV1?: { __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any } | null, googleServiceAccountKeyForSubmissions?: { __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any } | null, androidAppBuildCredentialsList: Array<{ __typename?: 'AndroidAppBuildCredentials', id: string, isDefault: boolean, isLegacy: boolean, name: string, androidKeystore?: { __typename?: 'AndroidKeystore', id: string, type: AndroidKeystoreType, keystore: string, keystorePassword: string, keyAlias: string, keyPassword?: string | null, md5CertificateFingerprint?: string | null, sha1CertificateFingerprint?: string | null, sha256CertificateFingerprint?: string | null, createdAt: any, updatedAt: any } | null }> } } };
export type CreateAndroidAppCredentialsMutation = { __typename?: 'RootMutation', androidAppCredentials: { __typename?: 'AndroidAppCredentialsMutation', createAndroidAppCredentials: { __typename?: 'AndroidAppCredentials', id: string, applicationIdentifier?: string | null, isLegacy: boolean, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, androidFcm?: { __typename?: 'AndroidFcm', id: string, credential: any, version: AndroidFcmVersion, createdAt: any, updatedAt: any, snippet: { __typename?: 'FcmSnippetLegacy', firstFourCharacters: string, lastFourCharacters: string } | { __typename?: 'FcmSnippetV1', projectId: string, keyId: string, serviceAccountEmail: string, clientId?: string | null } } | null, googleServiceAccountKeyForSubmissions?: { __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any } | null, androidAppBuildCredentialsList: Array<{ __typename?: 'AndroidAppBuildCredentials', id: string, isDefault: boolean, isLegacy: boolean, name: string, androidKeystore?: { __typename?: 'AndroidKeystore', id: string, type: AndroidKeystoreType, keystore: string, keystorePassword: string, keyAlias: string, keyPassword?: string | null, md5CertificateFingerprint?: string | null, sha1CertificateFingerprint?: string | null, sha256CertificateFingerprint?: string | null, createdAt: any, updatedAt: any } | null }> } } };
export type SetFcmMutationVariables = Exact<{
androidAppCredentialsId: Scalars['ID']['input'];
@@ -6151,7 +6118,7 @@ export type SetFcmMutationVariables = Exact<{
}>;
export type SetFcmMutation = { __typename?: 'RootMutation', androidAppCredentials: { __typename?: 'AndroidAppCredentialsMutation', setFcm: { __typename?: 'AndroidAppCredentials', id: string, applicationIdentifier?: string | null, isLegacy: boolean, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, androidFcm?: { __typename?: 'AndroidFcm', id: string, credential: any, version: AndroidFcmVersion, createdAt: any, updatedAt: any, snippet: { __typename?: 'FcmSnippetLegacy', firstFourCharacters: string, lastFourCharacters: string } | { __typename?: 'FcmSnippetV1', projectId: string, keyId: string, serviceAccountEmail: string, clientId?: string | null } } | null, googleServiceAccountKeyForFcmV1?: { __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any } | null, googleServiceAccountKeyForSubmissions?: { __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any } | null, androidAppBuildCredentialsList: Array<{ __typename?: 'AndroidAppBuildCredentials', id: string, isDefault: boolean, isLegacy: boolean, name: string, androidKeystore?: { __typename?: 'AndroidKeystore', id: string, type: AndroidKeystoreType, keystore: string, keystorePassword: string, keyAlias: string, keyPassword?: string | null, md5CertificateFingerprint?: string | null, sha1CertificateFingerprint?: string | null, sha256CertificateFingerprint?: string | null, createdAt: any, updatedAt: any } | null }> } } };
export type SetFcmMutation = { __typename?: 'RootMutation', androidAppCredentials: { __typename?: 'AndroidAppCredentialsMutation', setFcm: { __typename?: 'AndroidAppCredentials', id: string, applicationIdentifier?: string | null, isLegacy: boolean, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, androidFcm?: { __typename?: 'AndroidFcm', id: string, credential: any, version: AndroidFcmVersion, createdAt: any, updatedAt: any, snippet: { __typename?: 'FcmSnippetLegacy', firstFourCharacters: string, lastFourCharacters: string } | { __typename?: 'FcmSnippetV1', projectId: string, keyId: string, serviceAccountEmail: string, clientId?: string | null } } | null, googleServiceAccountKeyForSubmissions?: { __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any } | null, androidAppBuildCredentialsList: Array<{ __typename?: 'AndroidAppBuildCredentials', id: string, isDefault: boolean, isLegacy: boolean, name: string, androidKeystore?: { __typename?: 'AndroidKeystore', id: string, type: AndroidKeystoreType, keystore: string, keystorePassword: string, keyAlias: string, keyPassword?: string | null, md5CertificateFingerprint?: string | null, sha1CertificateFingerprint?: string | null, sha256CertificateFingerprint?: string | null, createdAt: any, updatedAt: any } | null }> } } };
export type SetGoogleServiceAccountKeyForSubmissionsMutationVariables = Exact<{
androidAppCredentialsId: Scalars['ID']['input'];
@@ -6159,15 +6126,7 @@ export type SetGoogleServiceAccountKeyForSubmissionsMutationVariables = Exact<{
}>;
export type SetGoogleServiceAccountKeyForSubmissionsMutation = { __typename?: 'RootMutation', androidAppCredentials: { __typename?: 'AndroidAppCredentialsMutation', setGoogleServiceAccountKeyForSubmissions: { __typename?: 'AndroidAppCredentials', id: string, applicationIdentifier?: string | null, isLegacy: boolean, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, androidFcm?: { __typename?: 'AndroidFcm', id: string, credential: any, version: AndroidFcmVersion, createdAt: any, updatedAt: any, snippet: { __typename?: 'FcmSnippetLegacy', firstFourCharacters: string, lastFourCharacters: string } | { __typename?: 'FcmSnippetV1', projectId: string, keyId: string, serviceAccountEmail: string, clientId?: string | null } } | null, googleServiceAccountKeyForFcmV1?: { __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any } | null, googleServiceAccountKeyForSubmissions?: { __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any } | null, androidAppBuildCredentialsList: Array<{ __typename?: 'AndroidAppBuildCredentials', id: string, isDefault: boolean, isLegacy: boolean, name: string, androidKeystore?: { __typename?: 'AndroidKeystore', id: string, type: AndroidKeystoreType, keystore: string, keystorePassword: string, keyAlias: string, keyPassword?: string | null, md5CertificateFingerprint?: string | null, sha1CertificateFingerprint?: string | null, sha256CertificateFingerprint?: string | null, createdAt: any, updatedAt: any } | null }> } } };
export type SetGoogleServiceAccountKeyForFcmV1MutationVariables = Exact<{
androidAppCredentialsId: Scalars['ID']['input'];
googleServiceAccountKeyId: Scalars['ID']['input'];
}>;
export type SetGoogleServiceAccountKeyForFcmV1Mutation = { __typename?: 'RootMutation', androidAppCredentials: { __typename?: 'AndroidAppCredentialsMutation', setGoogleServiceAccountKeyForFcmV1: { __typename?: 'AndroidAppCredentials', id: string, applicationIdentifier?: string | null, isLegacy: boolean, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, androidFcm?: { __typename?: 'AndroidFcm', id: string, credential: any, version: AndroidFcmVersion, createdAt: any, updatedAt: any, snippet: { __typename?: 'FcmSnippetLegacy', firstFourCharacters: string, lastFourCharacters: string } | { __typename?: 'FcmSnippetV1', projectId: string, keyId: string, serviceAccountEmail: string, clientId?: string | null } } | null, googleServiceAccountKeyForFcmV1?: { __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any } | null, googleServiceAccountKeyForSubmissions?: { __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any } | null, androidAppBuildCredentialsList: Array<{ __typename?: 'AndroidAppBuildCredentials', id: string, isDefault: boolean, isLegacy: boolean, name: string, androidKeystore?: { __typename?: 'AndroidKeystore', id: string, type: AndroidKeystoreType, keystore: string, keystorePassword: string, keyAlias: string, keyPassword?: string | null, md5CertificateFingerprint?: string | null, sha1CertificateFingerprint?: string | null, sha256CertificateFingerprint?: string | null, createdAt: any, updatedAt: any } | null }> } } };
export type SetGoogleServiceAccountKeyForSubmissionsMutation = { __typename?: 'RootMutation', androidAppCredentials: { __typename?: 'AndroidAppCredentialsMutation', setGoogleServiceAccountKeyForSubmissions: { __typename?: 'AndroidAppCredentials', id: string, applicationIdentifier?: string | null, isLegacy: boolean, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, androidFcm?: { __typename?: 'AndroidFcm', id: string, credential: any, version: AndroidFcmVersion, createdAt: any, updatedAt: any, snippet: { __typename?: 'FcmSnippetLegacy', firstFourCharacters: string, lastFourCharacters: string } | { __typename?: 'FcmSnippetV1', projectId: string, keyId: string, serviceAccountEmail: string, clientId?: string | null } } | null, googleServiceAccountKeyForSubmissions?: { __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any } | null, androidAppBuildCredentialsList: Array<{ __typename?: 'AndroidAppBuildCredentials', id: string, isDefault: boolean, isLegacy: boolean, name: string, androidKeystore?: { __typename?: 'AndroidKeystore', id: string, type: AndroidKeystoreType, keystore: string, keystorePassword: string, keyAlias: string, keyPassword?: string | null, md5CertificateFingerprint?: string | null, sha1CertificateFingerprint?: string | null, sha256CertificateFingerprint?: string | null, createdAt: any, updatedAt: any } | null }> } } };
export type CreateAndroidFcmMutationVariables = Exact<{
androidFcmInput: AndroidFcmInput;
@@ -6221,7 +6180,7 @@ export type CommonAndroidAppCredentialsWithBuildCredentialsByApplicationIdentifi
}>;
export type CommonAndroidAppCredentialsWithBuildCredentialsByApplicationIdentifierQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byFullName: { __typename?: 'App', id: string, androidAppCredentials: Array<{ __typename?: 'AndroidAppCredentials', id: string, applicationIdentifier?: string | null, isLegacy: boolean, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, androidFcm?: { __typename?: 'AndroidFcm', id: string, credential: any, version: AndroidFcmVersion, createdAt: any, updatedAt: any, snippet: { __typename?: 'FcmSnippetLegacy', firstFourCharacters: string, lastFourCharacters: string } | { __typename?: 'FcmSnippetV1', projectId: string, keyId: string, serviceAccountEmail: string, clientId?: string | null } } | null, googleServiceAccountKeyForFcmV1?: { __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any } | null, googleServiceAccountKeyForSubmissions?: { __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any } | null, androidAppBuildCredentialsList: Array<{ __typename?: 'AndroidAppBuildCredentials', id: string, isDefault: boolean, isLegacy: boolean, name: string, androidKeystore?: { __typename?: 'AndroidKeystore', id: string, type: AndroidKeystoreType, keystore: string, keystorePassword: string, keyAlias: string, keyPassword?: string | null, md5CertificateFingerprint?: string | null, sha1CertificateFingerprint?: string | null, sha256CertificateFingerprint?: string | null, createdAt: any, updatedAt: any } | null }> }> } } };
export type CommonAndroidAppCredentialsWithBuildCredentialsByApplicationIdentifierQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byFullName: { __typename?: 'App', id: string, androidAppCredentials: Array<{ __typename?: 'AndroidAppCredentials', id: string, applicationIdentifier?: string | null, isLegacy: boolean, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, androidFcm?: { __typename?: 'AndroidFcm', id: string, credential: any, version: AndroidFcmVersion, createdAt: any, updatedAt: any, snippet: { __typename?: 'FcmSnippetLegacy', firstFourCharacters: string, lastFourCharacters: string } | { __typename?: 'FcmSnippetV1', projectId: string, keyId: string, serviceAccountEmail: string, clientId?: string | null } } | null, googleServiceAccountKeyForSubmissions?: { __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any } | null, androidAppBuildCredentialsList: Array<{ __typename?: 'AndroidAppBuildCredentials', id: string, isDefault: boolean, isLegacy: boolean, name: string, androidKeystore?: { __typename?: 'AndroidKeystore', id: string, type: AndroidKeystoreType, keystore: string, keystorePassword: string, keyAlias: string, keyPassword?: string | null, md5CertificateFingerprint?: string | null, sha1CertificateFingerprint?: string | null, sha256CertificateFingerprint?: string | null, createdAt: any, updatedAt: any } | null }> }> } } };
export type GoogleServiceAccountKeyByAccountQueryVariables = Exact<{
accountName: Scalars['String']['input'];
@@ -6533,7 +6492,7 @@ export type CreateAndroidBuildMutationVariables = Exact<{
}>;
export type CreateAndroidBuildMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', createAndroidBuild: { __typename?: 'CreateBuildResult', build: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, resourceClass: BuildResourceClass, expirationDate?: any | null, isForIosSimulator: boolean, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } }, deprecationInfo?: { __typename?: 'EASBuildDeprecationInfo', type: EasBuildDeprecationInfoType, message: string } | null } } };
export type CreateAndroidBuildMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', createAndroidBuild: { __typename?: 'CreateBuildResult', build: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, resourceClass: BuildResourceClass, expirationDate?: any | null, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } }, deprecationInfo?: { __typename?: 'EASBuildDeprecationInfo', type: EasBuildDeprecationInfoType, message: string } | null } } };
export type CreateIosBuildMutationVariables = Exact<{
appId: Scalars['ID']['input'];
@@ -6543,7 +6502,7 @@ export type CreateIosBuildMutationVariables = Exact<{
}>;
export type CreateIosBuildMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', createIosBuild: { __typename?: 'CreateBuildResult', build: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, resourceClass: BuildResourceClass, expirationDate?: any | null, isForIosSimulator: boolean, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } }, deprecationInfo?: { __typename?: 'EASBuildDeprecationInfo', type: EasBuildDeprecationInfoType, message: string } | null } } };
export type CreateIosBuildMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', createIosBuild: { __typename?: 'CreateBuildResult', build: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, resourceClass: BuildResourceClass, expirationDate?: any | null, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } }, deprecationInfo?: { __typename?: 'EASBuildDeprecationInfo', type: EasBuildDeprecationInfoType, message: string } | null } } };
export type UpdateBuildMetadataMutationVariables = Exact<{
buildId: Scalars['ID']['input'];
@@ -6551,7 +6510,7 @@ export type UpdateBuildMetadataMutationVariables = Exact<{
}>;
export type UpdateBuildMetadataMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', updateBuildMetadata: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, resourceClass: BuildResourceClass, expirationDate?: any | null, isForIosSimulator: boolean, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } } } };
export type UpdateBuildMetadataMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', updateBuildMetadata: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, resourceClass: BuildResourceClass, expirationDate?: any | null, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } } } };
export type RetryIosBuildMutationVariables = Exact<{
buildId: Scalars['ID']['input'];
@@ -6559,7 +6518,7 @@ export type RetryIosBuildMutationVariables = Exact<{
}>;
export type RetryIosBuildMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', retryIosBuild: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, resourceClass: BuildResourceClass, expirationDate?: any | null, isForIosSimulator: boolean, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } } } };
export type RetryIosBuildMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', retryIosBuild: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, resourceClass: BuildResourceClass, expirationDate?: any | null, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } } } };
export type CreateEnvironmentSecretForAccountMutationVariables = Exact<{
input: CreateEnvironmentSecretInput;
@@ -6727,14 +6686,14 @@ export type BuildsByIdQueryVariables = Exact<{
}>;
export type BuildsByIdQuery = { __typename?: 'RootQuery', builds: { __typename?: 'BuildQuery', byId: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, resourceClass: BuildResourceClass, expirationDate?: any | null, isForIosSimulator: boolean, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } } } };
export type BuildsByIdQuery = { __typename?: 'RootQuery', builds: { __typename?: 'BuildQuery', byId: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, resourceClass: BuildResourceClass, expirationDate?: any | null, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } } } };
export type BuildsWithSubmissionsByIdQueryVariables = Exact<{
buildId: Scalars['ID']['input'];
}>;
export type BuildsWithSubmissionsByIdQuery = { __typename?: 'RootQuery', builds: { __typename?: 'BuildQuery', byId: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, resourceClass: BuildResourceClass, expirationDate?: any | null, isForIosSimulator: boolean, submissions: Array<{ __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logsUrl?: string | null, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null }>, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } } } };
export type BuildsWithSubmissionsByIdQuery = { __typename?: 'RootQuery', builds: { __typename?: 'BuildQuery', byId: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, resourceClass: BuildResourceClass, expirationDate?: any | null, submissions: Array<{ __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logsUrl?: string | null, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null }>, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } } } };
export type ViewBuildsOnAppQueryVariables = Exact<{
appId: Scalars['String']['input'];
@@ -6744,7 +6703,7 @@ export type ViewBuildsOnAppQueryVariables = Exact<{
}>;
export type ViewBuildsOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, builds: Array<{ __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, resourceClass: BuildResourceClass, expirationDate?: any | null, isForIosSimulator: boolean, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } }> } } };
export type ViewBuildsOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, builds: Array<{ __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, resourceClass: BuildResourceClass, expirationDate?: any | null, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } }> } } };
export type ViewUpdateChannelOnAppQueryVariables = Exact<{
appId: Scalars['String']['input'];
@@ -6886,9 +6845,9 @@ export type AccountFragment = { __typename?: 'Account', id: string, name: string
export type AppFragment = { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } };
export type BuildFragment = { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, resourceClass: BuildResourceClass, expirationDate?: any | null, isForIosSimulator: boolean, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } };
export type BuildFragment = { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, resourceClass: BuildResourceClass, expirationDate?: any | null, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } };
export type BuildWithSubmissionsFragment = { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, resourceClass: BuildResourceClass, expirationDate?: any | null, isForIosSimulator: boolean, submissions: Array<{ __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logsUrl?: string | null, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null }>, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } };
export type BuildWithSubmissionsFragment = { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, resourceClass: BuildResourceClass, expirationDate?: any | null, submissions: Array<{ __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logsUrl?: string | null, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null }>, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } };
export type EnvironmentSecretFragment = { __typename?: 'EnvironmentSecret', id: string, name: string, type: EnvironmentSecretType, createdAt: any };
@@ -6910,7 +6869,7 @@ export type WebhookFragment = { __typename?: 'Webhook', id: string, event: Webho
export type AndroidAppBuildCredentialsFragment = { __typename?: 'AndroidAppBuildCredentials', id: string, isDefault: boolean, isLegacy: boolean, name: string, androidKeystore?: { __typename?: 'AndroidKeystore', id: string, type: AndroidKeystoreType, keystore: string, keystorePassword: string, keyAlias: string, keyPassword?: string | null, md5CertificateFingerprint?: string | null, sha1CertificateFingerprint?: string | null, sha256CertificateFingerprint?: string | null, createdAt: any, updatedAt: any } | null };
export type CommonAndroidAppCredentialsFragment = { __typename?: 'AndroidAppCredentials', id: string, applicationIdentifier?: string | null, isLegacy: boolean, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, androidFcm?: { __typename?: 'AndroidFcm', id: string, credential: any, version: AndroidFcmVersion, createdAt: any, updatedAt: any, snippet: { __typename?: 'FcmSnippetLegacy', firstFourCharacters: string, lastFourCharacters: string } | { __typename?: 'FcmSnippetV1', projectId: string, keyId: string, serviceAccountEmail: string, clientId?: string | null } } | null, googleServiceAccountKeyForFcmV1?: { __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any } | null, googleServiceAccountKeyForSubmissions?: { __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any } | null, androidAppBuildCredentialsList: Array<{ __typename?: 'AndroidAppBuildCredentials', id: string, isDefault: boolean, isLegacy: boolean, name: string, androidKeystore?: { __typename?: 'AndroidKeystore', id: string, type: AndroidKeystoreType, keystore: string, keystorePassword: string, keyAlias: string, keyPassword?: string | null, md5CertificateFingerprint?: string | null, sha1CertificateFingerprint?: string | null, sha256CertificateFingerprint?: string | null, createdAt: any, updatedAt: any } | null }> };
export type CommonAndroidAppCredentialsFragment = { __typename?: 'AndroidAppCredentials', id: string, applicationIdentifier?: string | null, isLegacy: boolean, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, androidFcm?: { __typename?: 'AndroidFcm', id: string, credential: any, version: AndroidFcmVersion, createdAt: any, updatedAt: any, snippet: { __typename?: 'FcmSnippetLegacy', firstFourCharacters: string, lastFourCharacters: string } | { __typename?: 'FcmSnippetV1', projectId: string, keyId: string, serviceAccountEmail: string, clientId?: string | null } } | null, googleServiceAccountKeyForSubmissions?: { __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any } | null, androidAppBuildCredentialsList: Array<{ __typename?: 'AndroidAppBuildCredentials', id: string, isDefault: boolean, isLegacy: boolean, name: string, androidKeystore?: { __typename?: 'AndroidKeystore', id: string, type: AndroidKeystoreType, keystore: string, keystorePassword: string, keyAlias: string, keyPassword?: string | null, md5CertificateFingerprint?: string | null, sha1CertificateFingerprint?: string | null, sha256CertificateFingerprint?: string | null, createdAt: any, updatedAt: any } | null }> };
export type AndroidFcmFragment = { __typename?: 'AndroidFcm', id: string, credential: any, version: AndroidFcmVersion, createdAt: any, updatedAt: any, snippet: { __typename?: 'FcmSnippetLegacy', firstFourCharacters: string, lastFourCharacters: string } | { __typename?: 'FcmSnippetV1', projectId: string, keyId: string, serviceAccountEmail: string, clientId?: string | null } };
@@ -57,7 +57,6 @@ export const BuildFragmentNode = gql`
completedAt
resourceClass
expirationDate
isForIosSimulator
}
`;
@@ -18,10 +18,6 @@ export const CommonAndroidAppCredentialsFragmentNode = gql`
id
...AndroidFcmFragment
}
googleServiceAccountKeyForFcmV1 {
id
...GoogleServiceAccountKeyFragment
}
googleServiceAccountKeyForSubmissions {
id
...GoogleServiceAccountKeyFragment
@@ -1,13 +1,13 @@
import { Platform, Workflow } from '@expo/eas-build-job';
import { vol } from 'memfs';
import { resolveVcsClient } from '../../vcs';
import { getVcsClient } from '../../vcs';
import { resolveWorkflowAsync, resolveWorkflowPerPlatformAsync } from '../workflow';
jest.mock('fs');
const projectDir = '/app';
const vcsClient = resolveVcsClient();
const vcsClient = getVcsClient();
describe(resolveWorkflowAsync, () => {
beforeEach(() => {
@@ -7,7 +7,7 @@ import { ExpoGraphqlClient } from '../../../commandUtils/context/contextUtils/cr
import { jester, jester as mockJester } from '../../../credentials/__tests__/fixtures-constants';
import { AppQuery } from '../../../graphql/queries/AppQuery';
import { promptAsync } from '../../../prompts';
import { resolveVcsClient } from '../../../vcs';
import { getVcsClient } from '../../../vcs';
import {
ensureApplicationIdIsDefinedForManagedProjectAsync,
getApplicationIdAsync,
@@ -18,7 +18,7 @@ jest.mock('../../../prompts');
jest.mock('../../../graphql/queries/AppQuery');
jest.mock('../../../user/actions', () => ({ ensureLoggedInAsync: jest.fn(() => mockJester) }));
const vcsClient = resolveVcsClient();
const vcsClient = getVcsClient();
beforeEach(async () => {
vol.reset();
@@ -4,14 +4,14 @@ import os from 'os';
import { jester as mockJester } from '../../../credentials/__tests__/fixtures-constants';
import { promptAsync } from '../../../prompts';
import { resolveVcsClient } from '../../../vcs';
import { getVcsClient } from '../../../vcs';
import { resolveGradleBuildContextAsync } from '../gradle';
jest.mock('fs');
jest.mock('../../../prompts');
jest.mock('../../../user/actions', () => ({ ensureLoggedInAsync: jest.fn(() => mockJester) }));
const vcsClient = resolveVcsClient();
const vcsClient = getVcsClient();
beforeEach(async () => {
vol.reset();
@@ -41,7 +41,7 @@ export async function validateCustomBuildConfigAsync({
try {
const config = await readAndValidateBuildConfigAsync(configPath, {
skipNamespacedFunctionsOrFunctionGroupsCheck: true,
skipNamespacedFunctionsCheck: true,
});
return {
workflowName: config.build.name,
@@ -68,7 +68,3 @@ export async function validateCustomBuildConfigAsync({
export function getCustomBuildConfigPath(configFilename: string): string {
return path.join('.eas/build', configFilename);
}
export function getCustomBuildConfigPathForJob(configFilename: string): string {
return path.posix.join('.eas/build', configFilename);
}
@@ -8,7 +8,7 @@ import { ExpoGraphqlClient } from '../../../commandUtils/context/contextUtils/cr
import { jester, jester as mockJester } from '../../../credentials/__tests__/fixtures-constants';
import { AppQuery } from '../../../graphql/queries/AppQuery';
import { promptAsync } from '../../../prompts';
import { resolveVcsClient } from '../../../vcs';
import { getVcsClient } from '../../../vcs';
import {
ensureBundleIdentifierIsDefinedForManagedProjectAsync,
getBundleIdentifierAsync,
@@ -20,7 +20,7 @@ jest.mock('../../../prompts');
jest.mock('../../../graphql/queries/AppQuery');
jest.mock('../../../user/actions', () => ({ ensureLoggedInAsync: jest.fn(() => mockJester) }));
const vcsClient = resolveVcsClient();
const vcsClient = getVcsClient();
beforeEach(async () => {
vol.reset();
+13 -54
View File
@@ -88,17 +88,6 @@ export function isUsingEASUpdate(exp: ExpoConfig, projectId: string): boolean {
return exp.updates?.url === getEASUpdateURL(projectId);
}
async function getExpoUpdatesPackageVersionIfInstalledAsync(
projectDir: string
): Promise<string | null> {
const maybePackageJson = resolveFrom.silent(projectDir, 'expo-updates/package.json');
if (!maybePackageJson) {
return null;
}
const { version } = await fs.readJson(maybePackageJson);
return version ?? null;
}
export async function validateAppVersionRuntimePolicySupportAsync(
projectDir: string,
exp: ExpoConfig
@@ -107,13 +96,12 @@ export async function validateAppVersionRuntimePolicySupportAsync(
return;
}
const expoUpdatesPackageVersion = await getExpoUpdatesPackageVersionIfInstalledAsync(projectDir);
if (
expoUpdatesPackageVersion !== null &&
(semver.gte(expoUpdatesPackageVersion, '0.14.4') ||
expoUpdatesPackageVersion.includes('canary'))
) {
return;
const maybePackageJson = resolveFrom.silent(projectDir, 'expo-updates/package.json');
if (maybePackageJson) {
const { version } = await fs.readJson(maybePackageJson);
if (semver.gte(version, '0.14.4')) {
return;
}
}
Log.warn(
@@ -124,13 +112,13 @@ export async function validateAppVersionRuntimePolicySupportAsync(
export async function enforceRollBackToEmbeddedUpdateSupportAsync(
projectDir: string
): Promise<void> {
const expoUpdatesPackageVersion = await getExpoUpdatesPackageVersionIfInstalledAsync(projectDir);
if (
expoUpdatesPackageVersion !== null &&
(semver.gte(expoUpdatesPackageVersion, '0.19.0') ||
expoUpdatesPackageVersion.includes('canary'))
) {
return;
const maybePackageJson = resolveFrom.silent(projectDir, 'expo-updates/package.json');
if (maybePackageJson) {
const { version } = await fs.readJson(maybePackageJson);
if (semver.gte(version, '0.19.0')) {
return;
}
}
throw new Error(
@@ -140,35 +128,6 @@ export async function enforceRollBackToEmbeddedUpdateSupportAsync(
);
}
export async function isClassicUpdatesSupportedAsync(projectDir: string): Promise<boolean> {
const expoUpdatesPackageVersion = await getExpoUpdatesPackageVersionIfInstalledAsync(projectDir);
if (expoUpdatesPackageVersion === null) {
return false;
}
if (expoUpdatesPackageVersion.includes('canary')) {
return false;
}
return semver.lt(expoUpdatesPackageVersion, '0.19.0');
}
export async function isModernExpoUpdatesCLIWithRuntimeVersionCommandSupportedAsync(
projectDir: string
): Promise<boolean> {
const expoUpdatesPackageVersion = await getExpoUpdatesPackageVersionIfInstalledAsync(projectDir);
if (expoUpdatesPackageVersion === null) {
return false;
}
if (expoUpdatesPackageVersion.includes('canary')) {
return true;
}
// TODO(wschurman): add semver check once we know the SDK51 version of expo-updates that supports this
return false;
}
export async function installExpoUpdatesAsync(
projectDir: string,
options?: { silent: boolean }
+58 -96
View File
@@ -12,7 +12,6 @@ import nullthrows from 'nullthrows';
import path from 'path';
import promiseLimit from 'promise-limit';
import { isModernExpoUpdatesCLIWithRuntimeVersionCommandSupportedAsync } from './projectUtils';
import { resolveWorkflowAsync } from './workflow';
import { selectBranchOnAppAsync } from '../branch/queries';
import { getDefaultBranchNameAsync } from '../branch/utils';
@@ -25,17 +24,17 @@ import Log, { learnMore } from '../log';
import { RequestedPlatform, requestedPlatformDisplayNames } from '../platform';
import { promptAsync } from '../prompts';
import { getBranchNameFromChannelNameAsync } from '../update/getBranchNameFromChannelNameAsync';
import { formatUpdateMessage, truncateString as truncateUpdateMessage } from '../update/utils';
import {
UpdateJsonInfo,
formatUpdateMessage,
truncateString as truncateUpdateMessage,
} from '../update/utils';
import { PresignedPost, uploadWithPresignedPostWithRetryAsync } from '../uploads';
import {
expoCommandAsync,
shouldUseVersionedExpoCLI,
shouldUseVersionedExpoCLIWithExplicitPlatforms,
} from '../utils/expoCli';
import {
ExpoUpdatesCLIModuleNotFoundError,
expoUpdatesCommandAsync,
} from '../utils/expoUpdatesCli';
import chunk from '../utils/expodash/chunk';
import { truthy } from '../utils/expodash/filter';
import uniqBy from '../utils/expodash/uniqBy';
@@ -190,12 +189,14 @@ export async function buildBundlesAsync({
exp,
platformFlag,
clearCache,
dev = false,
}: {
projectDir: string;
inputDir: string;
exp: Pick<ExpoConfig, 'sdkVersion' | 'web'>;
platformFlag: ExpoCLIExportPlatformFlag;
clearCache?: boolean;
dev?: boolean;
}): Promise<void> {
const packageJSON = JsonFile.read(path.resolve(projectDir, 'package.json'));
if (!packageJSON) {
@@ -213,6 +214,7 @@ export async function buildBundlesAsync({
'--dump-sourcemap',
'--dump-assetmap',
`--platform=${platformFlag}`,
...(dev ? ['--dev'] : []),
...(clearCache ? ['--clear'] : []),
]);
}
@@ -232,6 +234,7 @@ export async function buildBundlesAsync({
'--dump-sourcemap',
'--dump-assetmap',
...platformArgs,
...(dev ? ['--dev'] : []),
...(clearCache ? ['--clear'] : []),
]);
}
@@ -253,6 +256,7 @@ export async function buildBundlesAsync({
'--dump-sourcemap',
'--dump-assetmap',
`--platform=${platformFlag}`,
...(dev ? ['--dev'] : []),
...(clearCache ? ['--clear'] : []),
]);
}
@@ -294,6 +298,14 @@ export function loadMetadata(distRoot: string): Metadata {
return metadata;
}
export async function generateEasMetadataAsync(
distRoot: string,
metadata: UpdateJsonInfo[]
): Promise<void> {
const easMetadataPath = path.join(distRoot, 'eas-update-metadata.json');
await JsonFile.writeAsync(easMetadataPath, { updates: metadata });
}
export function filterExportedPlatformsByFlag<T extends Partial<Record<Platform, any>>>(
record: T,
platformFlag: ExpoCLIExportPlatformFlag
@@ -563,7 +575,12 @@ export async function getBranchNameForCommandAsync({
}
if (channelNameArg) {
return await getBranchNameFromChannelNameAsync(graphqlClient, projectId, channelNameArg);
return await getBranchNameFromChannelNameAsync(
graphqlClient,
projectId,
channelNameArg,
paginatedQueryOptions
);
}
if (branchNameArg) {
@@ -680,100 +697,45 @@ export function getRequestedPlatform(
}
/** Get runtime versions grouped by platform. Runtime version is always `null` on web where the platform is always backwards compatible. */
export async function getRuntimeVersionObjectAsync({
exp,
platforms,
projectDir,
vcsClient,
}: {
exp: ExpoConfig;
platforms: Platform[];
projectDir: string;
vcsClient: Client;
}): Promise<{ platform: string; runtimeVersion: string }[]> {
return await Promise.all(
platforms.map(async platform => {
return {
platform,
runtimeVersion: await getRuntimeVersionForPlatformAsync({
exp,
platform,
projectDir,
vcsClient,
}),
};
})
);
}
async function getRuntimeVersionForPlatformAsync({
exp,
platform,
projectDir,
vcsClient,
}: {
exp: ExpoConfig;
platform: Platform;
projectDir: string;
vcsClient: Client;
}): Promise<string> {
if (platform === 'web') {
return 'UNVERSIONED';
export async function getRuntimeVersionObjectAsync(
exp: ExpoConfig,
platforms: Platform[],
projectDir: string,
vcsClient: Client
): Promise<{ platform: string; runtimeVersion: string }[]> {
for (const platform of platforms) {
if (platform === 'web') {
continue;
}
const isPolicy = typeof (exp[platform]?.runtimeVersion ?? exp.runtimeVersion) === 'object';
if (isPolicy) {
const isManaged =
(await resolveWorkflowAsync(projectDir, platform as EASBuildJobPlatform, vcsClient)) ===
Workflow.MANAGED;
if (!isManaged) {
throw new Error(
`You're currently using the bare workflow, where runtime version policies are not supported. You must set your runtime version manually. For example, define your runtime version as "1.0.0", not {"policy": "appVersion"} in your app config. ${learnMore(
'https://docs.expo.dev/eas-update/runtime-versions'
)}`
);
}
}
}
if (await isModernExpoUpdatesCLIWithRuntimeVersionCommandSupportedAsync(projectDir)) {
try {
const resolvedRuntimeVersionJSONResult = await expoUpdatesCommandAsync(projectDir, [
'runtimeversion:resolve',
'--platform',
platform,
]);
const runtimeVersionResult = JSON.parse(resolvedRuntimeVersionJSONResult);
if (runtimeVersionResult.fingerprintSources) {
Log.debug(`Resolved fingeprint runtime version for platform "${platform}". Sources:`);
Log.debug(runtimeVersionResult.fingerprintSources);
}
return nullthrows(
runtimeVersionResult.runtimeVersion,
return [...new Set(platforms)].map(platform => {
if (platform === 'web') {
return { platform: 'web', runtimeVersion: 'UNVERSIONED' };
}
return {
platform,
runtimeVersion: nullthrows(
Updates.getRuntimeVersion(exp, platform),
`Unable to determine runtime version for ${
requestedPlatformDisplayNames[platform]
}. ${learnMore('https://docs.expo.dev/eas-update/runtime-versions/')}`
);
} catch (e: any) {
// if it's a known set of errors thrown by the CLI it means that we need to default back to the
// previous behavior, otherwise we throw the error since something is wrong
if (!(e instanceof ExpoUpdatesCLIModuleNotFoundError)) {
throw e;
}
}
}
const runtimeVersion = exp[platform]?.runtimeVersion ?? exp.runtimeVersion;
if (typeof runtimeVersion === 'object') {
const workflow = await resolveWorkflowAsync(
projectDir,
platform as EASBuildJobPlatform,
vcsClient
);
if (workflow !== Workflow.MANAGED) {
throw new Error(
`You're currently using the bare workflow, where runtime version policies are not supported. You must set your runtime version manually. For example, define your runtime version as "1.0.0", not {"policy": "appVersion"} in your app config. ${learnMore(
'https://docs.expo.dev/eas-update/runtime-versions'
)}`
);
}
}
const resolvedRuntimeVersion = await Updates.getRuntimeVersionAsync(projectDir, exp, platform);
if (!resolvedRuntimeVersion) {
throw new Error(
`Unable to determine runtime version for ${
requestedPlatformDisplayNames[platform]
}. ${learnMore('https://docs.expo.dev/eas-update/runtime-versions/')}`
);
}
return resolvedRuntimeVersion;
),
};
});
}
export function getRuntimeToPlatformMappingFromRuntimeVersions(
@@ -1,45 +0,0 @@
import { ExpoConfig } from '@expo/config';
import { Updates } from '@expo/config-plugins';
import { isModernExpoUpdatesCLIWithRuntimeVersionCommandSupportedAsync } from './projectUtils';
import Log from '../log';
import {
ExpoUpdatesCLIModuleNotFoundError,
expoUpdatesCommandAsync,
} from '../utils/expoUpdatesCli';
export async function resolveRuntimeVersionAsync({
exp,
platform,
projectDir,
}: {
exp: ExpoConfig;
platform: 'ios' | 'android';
projectDir: string;
}): Promise<string | null> {
if (!(await isModernExpoUpdatesCLIWithRuntimeVersionCommandSupportedAsync(projectDir))) {
// fall back to the previous behavior (using the @expo/config-plugins eas-cli dependency rather
// than the versioned @expo/config-plugins dependency in the project)
return await Updates.getRuntimeVersionNullableAsync(projectDir, exp, platform);
}
try {
const resolvedRuntimeVersionJSONResult = await expoUpdatesCommandAsync(projectDir, [
'runtimeversion:resolve',
'--platform',
platform,
]);
const runtimeVersionResult = JSON.parse(resolvedRuntimeVersionJSONResult);
if (runtimeVersionResult.fingerprintSources) {
Log.debug(`Resolved fingeprint runtime version for platform "${platform}". Sources:`);
Log.debug(runtimeVersionResult.fingerprintSources);
}
return runtimeVersionResult.runtimeVersion ?? null;
} catch (e: any) {
// if expo-updates is not installed, there's no need for a runtime version in the build
if (e instanceof ExpoUpdatesCLIModuleNotFoundError) {
return null;
}
throw e;
}
}
@@ -1,3 +1,4 @@
import { Updates } from '@expo/config-plugins';
import assert from 'assert';
import { SelectRuntime } from './SelectRuntime';
@@ -23,7 +24,6 @@ import {
} from '../../graphql/queries/ChannelQuery';
import { UpdateQuery } from '../../graphql/queries/UpdateQuery';
import Log from '../../log';
import { resolveRuntimeVersionAsync } from '../../project/resolveRuntimeVersionAsync';
import { confirmAsync, promptAsync } from '../../prompts';
import { truthy } from '../../utils/expodash/filter';
import {
@@ -272,13 +272,9 @@ export class CreateRollout implements EASUpdateAction<UpdateChannelBasicInfoFrag
async selectRuntimeVersionFromProjectConfigAsync(ctx: EASUpdateContext): Promise<string> {
const platforms: ('ios' | 'android')[] = ['ios', 'android'];
const runtimes = (
await Promise.all(
platforms.map(platform =>
resolveRuntimeVersionAsync({ projectDir: ctx.app.projectDir, exp: ctx.app.exp, platform })
)
)
).filter(truthy);
const runtimes = platforms
.map(platform => Updates.getRuntimeVersion(ctx.app.exp, platform))
.filter(truthy);
const dedupedRuntimes = [...new Set(runtimes)];
if (dedupedRuntimes.length === 0) {
+2 -2
View File
@@ -1,4 +1,4 @@
import { AppPlatform, BuildFragment, BuildStatus } from '../graphql/generated';
import { AppPlatform, BuildFragment, BuildStatus, DistributionType } from '../graphql/generated';
function isAab(build: BuildFragment): boolean {
return build.artifacts?.applicationArchiveUrl?.endsWith('.aab') ?? false;
@@ -12,7 +12,7 @@ export function isRunnableOnSimulatorOrEmulator(build: BuildFragment): boolean {
return (
build.status === BuildStatus.Finished &&
!!build.artifacts?.applicationArchiveUrl &&
((build.platform === AppPlatform.Ios && build.isForIosSimulator) ||
((build.platform === AppPlatform.Ios && build.distribution === DistributionType.Simulator) ||
(build.platform === AppPlatform.Android && !isAab(build))) &&
!didArtifactsExpire(build)
);
@@ -3,7 +3,7 @@ import chalk from 'chalk';
import fs from 'fs-extra';
import nullthrows from 'nullthrows';
import { SetUpGoogleServiceAccountKeyForSubmissions } from '../../credentials/android/actions/SetUpGoogleServiceAccountKeyForSubmissions';
import { SetUpGoogleServiceAccountKey } from '../../credentials/android/actions/SetUpGoogleServiceAccountKey';
import { readAndValidateServiceAccountKey } from '../../credentials/android/utils/googleServiceAccountKey';
import Log, { learnMore } from '../../log';
import {
@@ -126,9 +126,7 @@ export async function getServiceAccountFromCredentialsServiceAsync(
Log.log(
`Looking up credentials configuration for ${appLookupParams.androidApplicationIdentifier}...`
);
const setupGoogleServiceAccountKeyAction = new SetUpGoogleServiceAccountKeyForSubmissions(
appLookupParams
);
const setupGoogleServiceAccountKeyAction = new SetUpGoogleServiceAccountKey(appLookupParams);
const androidAppCredentials = await setupGoogleServiceAccountKeyAction.runAsync(
ctx.credentialsCtx
);
@@ -20,7 +20,7 @@ import {
import { SubmissionMutation } from '../../../graphql/mutations/SubmissionMutation';
import { createTestProject } from '../../../project/__tests__/project-utils';
import { getOwnerAccountForProjectIdAsync } from '../../../project/projectUtils';
import { resolveVcsClient } from '../../../vcs';
import { getVcsClient } from '../../../vcs';
import {
ArchiveResolverContext,
ArchiveSource,
@@ -57,7 +57,7 @@ jest.mock('../../commons', () => {
};
});
const vcsClient = resolveVcsClient();
const vcsClient = getVcsClient();
describe(AndroidSubmitCommand, () => {
const testProject = createTestProject(testProjectId, mockJester.accounts[0].name, {
@@ -11,11 +11,11 @@ import {
jester as mockJester,
testProjectId,
} from '../../../credentials/__tests__/fixtures-constants';
import { SetUpGoogleServiceAccountKeyForSubmissions } from '../../../credentials/android/actions/SetUpGoogleServiceAccountKeyForSubmissions';
import { SetUpGoogleServiceAccountKey } from '../../../credentials/android/actions/SetUpGoogleServiceAccountKey';
import { createTestProject } from '../../../project/__tests__/project-utils';
import { getOwnerAccountForProjectIdAsync } from '../../../project/projectUtils';
import { promptAsync } from '../../../prompts';
import { resolveVcsClient } from '../../../vcs';
import { getVcsClient } from '../../../vcs';
import { createSubmissionContextAsync } from '../../context';
import {
ServiceAccountSource,
@@ -27,7 +27,7 @@ import {
jest.mock('fs');
jest.mock('../../../prompts');
jest.mock('../../../project/projectUtils');
jest.mock('../../../credentials/android/actions/SetUpGoogleServiceAccountKeyForSubmissions');
jest.mock('../../../credentials/android/actions/SetUpGoogleServiceAccountKey');
jest.mock('../../../user/User', () => ({
getUserAsync: jest.fn(() => mockJester),
}));
@@ -45,7 +45,7 @@ const mockDetectableServiceAccountJson = JSON.stringify({
client_email: '[email protected]',
});
const vcsClient = resolveVcsClient();
const vcsClient = getVcsClient();
beforeAll(() => {
vol.fromJSON({
@@ -55,7 +55,7 @@ beforeAll(() => {
'/other_dir/invalid_file.txt': 'this is not even a JSON',
});
jest
.spyOn(SetUpGoogleServiceAccountKeyForSubmissions.prototype, 'runAsync')
.spyOn(SetUpGoogleServiceAccountKey.prototype, 'runAsync')
.mockImplementation(async () => testAndroidAppCredentialsFragment);
});
afterAll(() => {
@@ -111,11 +111,6 @@ export default class IosSubmitCommand {
const envAppSpecificPassword = getenv.string('EXPO_APPLE_APP_SPECIFIC_PASSWORD', '');
if (envAppSpecificPassword) {
if (!/^[a-z]{4}-[a-z]{4}-[a-z]{4}-[a-z]{4}$/.test(envAppSpecificPassword)) {
throw new Error(
'EXPO_APPLE_APP_SPECIFIC_PASSWORD must be in the format xxxx-xxxx-xxxx-xxxx, where x is a lowercase letter.'
);
}
return result({
sourceType: AppSpecificPasswordSourceType.userDefined,
appSpecificPassword: envAppSpecificPassword,
@@ -17,7 +17,7 @@ import { AppQuery } from '../../../graphql/queries/AppQuery';
import { createTestProject } from '../../../project/__tests__/project-utils';
import { getBundleIdentifierAsync } from '../../../project/ios/bundleIdentifier';
import { promptAsync } from '../../../prompts';
import { resolveVcsClient } from '../../../vcs';
import { getVcsClient } from '../../../vcs';
import { SubmissionContext, createSubmissionContextAsync } from '../../context';
import {
AscApiKeySource,
@@ -42,7 +42,7 @@ const testProject = createTestProject(testProjectId, mockJester.accounts[0].name
});
const projectId = uuidv4();
const vcsClient = resolveVcsClient();
const vcsClient = getVcsClient();
async function getIosSubmissionContextAsync(): Promise<SubmissionContext<Platform.IOS>> {
const graphqlClient = instance(mock<ExpoGraphqlClient>());
@@ -13,7 +13,7 @@ import { BuildFragment, SubmissionArchiveSourceType } from '../../../graphql/gen
import { SubmissionMutation } from '../../../graphql/mutations/SubmissionMutation';
import { createTestProject } from '../../../project/__tests__/project-utils';
import { getOwnerAccountForProjectIdAsync } from '../../../project/projectUtils';
import { resolveVcsClient } from '../../../vcs';
import { getVcsClient } from '../../../vcs';
import {
ArchiveResolverContext,
ArchiveSource,
@@ -53,7 +53,7 @@ jest.mock('../../commons', () => {
};
});
const vcsClient = resolveVcsClient();
const vcsClient = getVcsClient();
describe(IosSubmitCommand, () => {
const testProject = createTestProject(testProjectId, mockJester.accounts[0].name, {});
@@ -78,43 +78,6 @@ describe(IosSubmitCommand, () => {
jest.mocked(getOwnerAccountForProjectIdAsync).mockResolvedValue(mockJester.accounts[0]);
});
it('throws an error if using app specific password in invalid format', async () => {
const projectId = uuidv4();
const graphqlClient = {} as any as ExpoGraphqlClient;
const analytics = instance(mock<Analytics>());
jest
.mocked(getArchiveAsync)
.mockImplementation(jest.requireActual('../../ArchiveSource').getArchiveAsync);
process.env.EXPO_APPLE_APP_SPECIFIC_PASSWORD = 'ls -la';
const ctx = await createSubmissionContextAsync({
platform: Platform.IOS,
projectDir: testProject.projectRoot,
archiveFlags: {
url: 'http://expo.dev/fake.ipa',
},
profile: {
language: 'en-US',
appleId: '[email protected]',
ascAppId: '12345678',
},
nonInteractive: false,
actor: mockJester,
graphqlClient,
analytics,
exp: testProject.appJSON.expo,
projectId,
vcsClient,
});
const command = new IosSubmitCommand(ctx);
await expect(command.runAsync()).rejects.toThrow(
'EXPO_APPLE_APP_SPECIFIC_PASSWORD must be in the format xxxx-xxxx-xxxx-xxxx, where x is a lowercase letter.'
);
delete process.env.EXPO_APPLE_APP_SPECIFIC_PASSWORD;
});
describe('non-interactive mode', () => {
it("throws error if didn't provide appleId and ascAppId in the submit profile", async () => {
const projectId = uuidv4();
@@ -155,7 +118,7 @@ describe(IosSubmitCommand, () => {
.mocked(getArchiveAsync)
.mockImplementation(jest.requireActual('../../ArchiveSource').getArchiveAsync);
process.env.EXPO_APPLE_APP_SPECIFIC_PASSWORD = 'abcd-abcd-abcd-abcd';
process.env.EXPO_APPLE_APP_SPECIFIC_PASSWORD = 'supersecret';
const ctx = await createSubmissionContextAsync({
platform: Platform.IOS,
@@ -184,7 +147,7 @@ describe(IosSubmitCommand, () => {
archiveSource: { type: SubmissionArchiveSourceType.Url, url: 'http://expo.dev/fake.ipa' },
config: {
appleIdUsername: '[email protected]',
appleAppSpecificPassword: 'abcd-abcd-abcd-abcd',
appleAppSpecificPassword: 'supersecret',
ascAppIdentifier: '12345678',
},
});
@@ -219,7 +182,7 @@ describe(IosSubmitCommand, () => {
return ctx;
});
process.env.EXPO_APPLE_APP_SPECIFIC_PASSWORD = 'abcd-abcd-abcd-abcd';
process.env.EXPO_APPLE_APP_SPECIFIC_PASSWORD = 'supersecret';
const ctx = await createSubmissionContextAsync({
platform: Platform.IOS,
@@ -246,7 +209,7 @@ describe(IosSubmitCommand, () => {
submittedBuildId: selectedBuild.id,
config: {
appleIdUsername: '[email protected]',
appleAppSpecificPassword: 'abcd-abcd-abcd-abcd',
appleAppSpecificPassword: 'supersecret',
ascAppIdentifier: '87654321',
},
archiveSource: undefined,
@@ -276,7 +239,7 @@ describe(IosSubmitCommand, () => {
return ctx;
});
process.env.EXPO_APPLE_APP_SPECIFIC_PASSWORD = 'abcd-abcd-abcd-abcd';
process.env.EXPO_APPLE_APP_SPECIFIC_PASSWORD = 'supersecret';
const ctx = await createSubmissionContextAsync({
platform: Platform.IOS,
@@ -303,7 +266,7 @@ describe(IosSubmitCommand, () => {
submittedBuildId: selectedBuild.id,
config: {
appleIdUsername: '[email protected]',
appleAppSpecificPassword: 'abcd-abcd-abcd-abcd',
appleAppSpecificPassword: 'supersecret',
ascAppIdentifier: '12345678',
},
archiveSource: undefined,
@@ -338,7 +301,7 @@ describe(IosSubmitCommand, () => {
return ctx;
});
process.env.EXPO_APPLE_APP_SPECIFIC_PASSWORD = 'abcd-abcd-abcd-abcd';
process.env.EXPO_APPLE_APP_SPECIFIC_PASSWORD = 'supersecret';
const ctx = await createSubmissionContextAsync({
platform: Platform.IOS,
@@ -366,7 +329,7 @@ describe(IosSubmitCommand, () => {
submittedBuildId: selectedBuild.id,
config: {
appleIdUsername: '[email protected]',
appleAppSpecificPassword: 'abcd-abcd-abcd-abcd',
appleAppSpecificPassword: 'supersecret',
ascAppIdentifier: '12345678',
},
archiveSource: undefined,
@@ -1,13 +1,22 @@
import { instance, mock } from 'ts-mockito';
import { selectBranchOnAppAsync } from '../../branch/queries';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { updateChannelBranchMappingAsync } from '../../commands/channel/edit';
import { App, Runtime, UpdateBranch, UpdateChannel, UpdateInsights } from '../../graphql/generated';
import { ChannelQuery } from '../../graphql/queries/ChannelQuery';
import { getBranchNameFromChannelNameAsync } from '../getBranchNameFromChannelNameAsync';
jest.mock('../../graphql/queries/ChannelQuery');
jest.mock('../../graphql/queries/BranchQuery');
jest.mock('../../branch/queries');
jest.mock('../../commands/channel/edit');
const defaultPaginatedQueryOptions = {
json: false,
nonInteractive: false,
offset: 0,
};
describe(getBranchNameFromChannelNameAsync, () => {
beforeEach(() => {
jest.resetAllMocks();
@@ -26,13 +35,14 @@ describe(getBranchNameFromChannelNameAsync, () => {
const result = await getBranchNameFromChannelNameAsync(
graphqlClient,
'test-project-id',
'channel-name'
'channel-name',
defaultPaginatedQueryOptions
);
expect(result).toBe('test-branch-name');
});
test('errors when no branch is connected to channel', async () => {
test('prompts user to select a branch if no branch is connected to channel', async () => {
const graphqlClient = instance(mock<ExpoGraphqlClient>());
jest.mocked(ChannelQuery.viewUpdateChannelAsync).mockImplementationOnce(
async () =>
@@ -41,11 +51,24 @@ describe(getBranchNameFromChannelNameAsync, () => {
}) as any
);
expect(
getBranchNameFromChannelNameAsync(graphqlClient, 'test-project-id', 'test-channel-name')
).rejects.toThrow(
"Channel has no branches associated with it. Run 'eas channel:edit' to map a branch"
jest
.mocked(selectBranchOnAppAsync)
.mockImplementationOnce(async () => mockUpdateBranches(['test-branch-name'])[0] as any);
jest.mocked(updateChannelBranchMappingAsync).mockImplementationOnce(
async () =>
mockUpdateChannel({
channelName: 'test-channel-name',
branchNames: ['test-branch-name'],
}) as any
);
const result = await getBranchNameFromChannelNameAsync(
graphqlClient,
'test-project-id',
'test-channel-name',
defaultPaginatedQueryOptions
);
expect(result).toBe('test-branch-name');
});
test('errors when more than one branch is connected to channel', async () => {
@@ -59,7 +82,12 @@ describe(getBranchNameFromChannelNameAsync, () => {
);
expect(
getBranchNameFromChannelNameAsync(graphqlClient, 'test-project-id', 'test-channel-name')
getBranchNameFromChannelNameAsync(
graphqlClient,
'test-project-id',
'test-channel-name',
defaultPaginatedQueryOptions
)
).rejects.toThrow(
"Channel has multiple branches associated with it. Instead, use '--branch' instead of '--channel'"
);
@@ -78,7 +106,8 @@ describe(getBranchNameFromChannelNameAsync, () => {
const result = await getBranchNameFromChannelNameAsync(
graphqlClient,
'test-project-id',
'test-channel-name'
'test-channel-name',
defaultPaginatedQueryOptions
);
expect(result).toBe('test-branch-name');
@@ -1,36 +1,31 @@
import { ExpoConfig } from '@expo/config';
import { AndroidConfig, AndroidManifest, XML } from '@expo/config-plugins';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { RequestedPlatform } from '../../platform';
import { isModernExpoUpdatesCLIWithRuntimeVersionCommandSupportedAsync } from '../../project/projectUtils';
import { expoUpdatesCommandAsync } from '../../utils/expoUpdatesCli';
import { getOwnerAccountForProjectIdAsync } from '../../project/projectUtils';
import { ensureValidVersions } from '../utils';
/**
* Synchronize updates configuration to native files. This needs to do essentially the same thing as `withUpdates`
*/
export async function syncUpdatesConfigurationAsync(
graphqlClient: ExpoGraphqlClient,
projectDir: string,
exp: ExpoConfig
exp: ExpoConfig,
projectId: string
): Promise<void> {
ensureValidVersions(exp, RequestedPlatform.Android);
if (await isModernExpoUpdatesCLIWithRuntimeVersionCommandSupportedAsync(projectDir)) {
await expoUpdatesCommandAsync(projectDir, [
'configuration:syncnative',
'--platform',
'android',
]);
return;
}
const accountName = (await getOwnerAccountForProjectIdAsync(graphqlClient, projectId)).name;
// sync AndroidManifest.xml
const androidManifestPath = await AndroidConfig.Paths.getAndroidManifestAsync(projectDir);
const androidManifest = await getAndroidManifestAsync(projectDir);
const updatedAndroidManifest = await AndroidConfig.Updates.setUpdatesConfigAsync(
const updatedAndroidManifest = AndroidConfig.Updates.setUpdatesConfig(
projectDir,
exp,
androidManifest
androidManifest,
accountName
);
await AndroidConfig.Manifest.writeAndroidManifestAsync(
androidManifestPath,
@@ -42,14 +37,10 @@ export async function syncUpdatesConfigurationAsync(
const stringsResourceXML = await AndroidConfig.Resources.readResourcesXMLAsync({
path: stringsJSONPath,
});
// TODO(wschurman): this dependency needs to be updated for fingerprint
const updatedStringsResourceXML =
await AndroidConfig.Updates.applyRuntimeVersionFromConfigForProjectRootAsync(
projectDir,
exp,
stringsResourceXML
);
const updatedStringsResourceXML = AndroidConfig.Updates.applyRuntimeVersionFromConfig(
exp,
stringsResourceXML
);
await XML.writeXMLAsync({ path: stringsJSONPath, xml: updatedStringsResourceXML });
}
+81 -18
View File
@@ -8,16 +8,18 @@ import semver from 'semver';
import { syncUpdatesConfigurationAsync as syncAndroidUpdatesConfigurationAsync } from './android/UpdatesModule';
import { syncUpdatesConfigurationAsync as syncIosUpdatesConfigurationAsync } from './ios/UpdatesModule';
import { getEASUpdateURL } from '../api';
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
import { AppPlatform } from '../graphql/generated';
import Log, { learnMore } from '../log';
import { RequestedPlatform, appPlatformDisplayNames } from '../platform';
import { createOrModifyExpoConfigAsync } from '../project/expoConfig';
import { createOrModifyExpoConfigAsync, isUsingStaticExpoConfig } from '../project/expoConfig';
import {
installExpoUpdatesAsync,
isExpoUpdatesInstalledAsDevDependency,
isExpoUpdatesInstalledOrAvailable,
} from '../project/projectUtils';
import { resolveWorkflowPerPlatformAsync } from '../project/workflow';
import { confirmAsync } from '../prompts';
import { Client } from '../vcs/vcs';
export const DEFAULT_MANAGED_RUNTIME_VERSION_GTE_SDK_49 = { policy: 'appVersion' } as const;
@@ -231,7 +233,7 @@ function warnEASUpdatesManualConfig({
)}`
);
Log.warn(
`Add the following EAS Update key-values to the project app.config.js:\n${learnMore(
`Finish configuring EAS Update by adding the following to the project app.config.js:\n${learnMore(
'https://expo.fyi/eas-update-config'
)}\n`
);
@@ -258,26 +260,29 @@ function warnEASUpdatesManualConfig({
* Make sure that the current `app.json` configuration for EAS Updates is set natively.
*/
async function ensureEASUpdateIsConfiguredNativelyAsync(
graphqlClient: ExpoGraphqlClient,
vcsClient: Client,
{
exp,
projectId,
projectDir,
platform,
workflows,
}: {
exp: ExpoConfig;
projectId: string;
projectDir: string;
platform: RequestedPlatform;
workflows: Record<Platform, Workflow>;
}
): Promise<void> {
if (['all', 'android'].includes(platform) && workflows.android === Workflow.GENERIC) {
await syncAndroidUpdatesConfigurationAsync(projectDir, exp);
await syncAndroidUpdatesConfigurationAsync(graphqlClient, projectDir, exp, projectId);
Log.withTick(`Configured ${chalk.bold('AndroidManifest.xml')} for EAS Update`);
}
if (['all', 'ios'].includes(platform) && workflows.ios === Workflow.GENERIC) {
await syncIosUpdatesConfigurationAsync(vcsClient, projectDir, exp);
await syncIosUpdatesConfigurationAsync(graphqlClient, vcsClient, projectDir, exp, projectId);
Log.withTick(`Configured ${chalk.bold('Expo.plist')} for EAS Update`);
}
}
@@ -351,19 +356,30 @@ export async function ensureEASUpdateIsConfiguredInEasJsonAsync(projectDir: stri
* - Sets `updates.url` if not set
* - Ensure latest changes are reflected in the native config, if any
*/
export async function ensureEASUpdateIsConfiguredAsync({
exp: expMaybeWithoutUpdates,
projectId,
projectDir,
vcsClient,
platform,
}: {
exp: ExpoConfig;
projectId: string;
projectDir: string;
vcsClient: Client;
platform: RequestedPlatform | null;
}): Promise<void> {
export async function ensureEASUpdateIsConfiguredAsync(
graphqlClient: ExpoGraphqlClient,
{
exp: expMaybeWithoutUpdates,
projectId,
projectDir,
vcsClient,
platform,
}: {
exp: ExpoConfig;
projectId: string;
projectDir: string;
vcsClient: Client;
platform: RequestedPlatform | null;
}
): Promise<void> {
// EAS Update and SDK 49's "useClassicUpdates" option are mutually exclusive
if (expMaybeWithoutUpdates.updates?.useClassicUpdates) {
expMaybeWithoutUpdates = await ensureUseClassicUpdatesIsRemovedAsync({
exp: expMaybeWithoutUpdates,
projectDir,
});
}
const hasExpoUpdates = isExpoUpdatesInstalledOrAvailable(
projectDir,
expMaybeWithoutUpdates.sdkVersion
@@ -395,9 +411,10 @@ export async function ensureEASUpdateIsConfiguredAsync({
});
if (projectChanged || !hasExpoUpdates) {
await ensureEASUpdateIsConfiguredNativelyAsync(vcsClient, {
await ensureEASUpdateIsConfiguredNativelyAsync(graphqlClient, vcsClient, {
exp: expWithUpdates,
projectDir,
projectId,
platform,
workflows,
});
@@ -411,3 +428,49 @@ export async function ensureEASUpdateIsConfiguredAsync({
Log.newLine();
}
}
export async function ensureUseClassicUpdatesIsRemovedAsync({
exp: expMaybeWithoutUpdates,
projectDir,
}: {
exp: ExpoConfig;
projectDir: string;
}): Promise<ExpoConfig> {
if (!isUsingStaticExpoConfig(projectDir)) {
throw new Error(
`Your app config sets "updates.useClassicUpdates" but EAS Update does not support classic updates. Remove "useClassicUpdates" from your app config and run this command again.`
);
}
const shouldEditConfig = await confirmAsync({
message: `Your app config sets "updates.useClassicUpdates" but EAS Update does not support classic updates. Remove "updates.useClassicUpdates" from your app config?`,
});
if (!shouldEditConfig) {
throw new Error(
`Manually remove "updates.useClassicUpdates" from your app config and run this command again.`
);
}
const editedExpoConfig = mergeExpoConfig(expMaybeWithoutUpdates, {
updates: { useClassicUpdates: undefined },
}) as ExpoConfig;
const result = await createOrModifyExpoConfigAsync(projectDir, editedExpoConfig);
switch (result.type) {
case 'success':
Log.withTick(`Removed "updates.useClassicUpdates"`);
expMaybeWithoutUpdates = editedExpoConfig;
break;
case 'warn':
case 'fail':
throw new Error(result.message);
default:
throw new Error(
`Unexpected result type "${result.type}" received when modifying the project config.`
);
}
return editedExpoConfig;
}
@@ -1,13 +1,18 @@
import { ensureBranchExistsAsync } from '../branch/queries';
import { ensureBranchExistsAsync, selectBranchOnAppAsync } from '../branch/queries';
import { getAlwaysTrueBranchMapping } from '../channel/branch-mapping';
import { ChannelNotFoundError } from '../channel/errors';
import { createChannelOnAppAsync } from '../channel/queries';
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
import { PaginatedQueryOptions } from '../commandUtils/pagination';
import { updateChannelBranchMappingAsync } from '../commands/channel/edit';
import { ChannelQuery } from '../graphql/queries/ChannelQuery';
import Log from '../log';
export async function getBranchNameFromChannelNameAsync(
graphqlClient: ExpoGraphqlClient,
projectId: string,
channelName: string
channelName: string,
paginatedQueryOptions: PaginatedQueryOptions
): Promise<string> {
let branchName;
@@ -20,9 +25,19 @@ export async function getBranchNameFromChannelNameAsync(
if (channel.updateBranches.length === 1) {
branchName = channel.updateBranches[0].name;
} else if (channel.updateBranches.length === 0) {
throw new Error(
"Channel has no branches associated with it. Run 'eas channel:edit' to map a branch"
);
Log.log('Channel has no branches associated with it.');
const branch = await selectBranchOnAppAsync(graphqlClient, {
projectId,
promptTitle: `Which branch would you like ${channel.name} to point at?`,
displayTextForListItem: updateBranch => ({ title: updateBranch.name }),
paginatedQueryOptions,
});
await updateChannelBranchMappingAsync(graphqlClient, {
channelId: channel.id,
branchMapping: JSON.stringify(getAlwaysTrueBranchMapping(branch.id)),
});
return branch.name;
} else {
throw new Error(
`Channel has multiple branches associated with it. Instead, use '--branch' instead of '--channel'`
@@ -1,31 +1,28 @@
import { ExpoConfig } from '@expo/config';
import { IOSConfig } from '@expo/config-plugins';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { RequestedPlatform } from '../../platform';
import { isModernExpoUpdatesCLIWithRuntimeVersionCommandSupportedAsync } from '../../project/projectUtils';
import { expoUpdatesCommandAsync } from '../../utils/expoUpdatesCli';
import { getOwnerAccountForProjectIdAsync } from '../../project/projectUtils';
import { readPlistAsync, writePlistAsync } from '../../utils/plist';
import { Client } from '../../vcs/vcs';
import { ensureValidVersions } from '../utils';
export async function syncUpdatesConfigurationAsync(
graphqlClient: ExpoGraphqlClient,
vcsClient: Client,
projectDir: string,
exp: ExpoConfig
exp: ExpoConfig,
projectId: string
): Promise<void> {
ensureValidVersions(exp, RequestedPlatform.Ios);
if (await isModernExpoUpdatesCLIWithRuntimeVersionCommandSupportedAsync(projectDir)) {
await expoUpdatesCommandAsync(projectDir, ['configuration:syncnative', '--platform', 'ios']);
return;
}
const accountName = (await getOwnerAccountForProjectIdAsync(graphqlClient, projectId)).name;
const expoPlist = await readExpoPlistAsync(projectDir);
// TODO(wschurman): this dependency needs to be updated for fingerprint
const updatedExpoPlist = await IOSConfig.Updates.setUpdatesConfigAsync(
const updatedExpoPlist = IOSConfig.Updates.setUpdatesConfig(
projectDir,
exp,
expoPlist
expoPlist,
accountName
);
await writeExpoPlistAsync(vcsClient, projectDir, updatedExpoPlist);
}
@@ -1,36 +0,0 @@
import spawnAsync from '@expo/spawn-async';
import resolveFrom, { silent as silentResolveFrom } from 'resolve-from';
import { link } from '../log';
export class ExpoUpdatesCLIModuleNotFoundError extends Error {}
export class ExpoUpdatesCLIInvalidCommandError extends Error {}
export async function expoUpdatesCommandAsync(projectDir: string, args: string[]): Promise<string> {
let expoUpdatesCli;
try {
expoUpdatesCli =
silentResolveFrom(projectDir, 'expo-updates/bin/cli') ??
resolveFrom(projectDir, 'expo-updates/bin/cli.js');
} catch (e: any) {
if (e.code === 'MODULE_NOT_FOUND') {
throw new ExpoUpdatesCLIModuleNotFoundError(
`The \`expo-updates\` package was not found. Follow the installation directions at ${link(
'https://docs.expo.dev/bare/installing-expo-modules/'
)}`
);
}
throw e;
}
try {
return (await spawnAsync(expoUpdatesCli, args)).stdout;
} catch (e: any) {
if (e.stderr && typeof e.stderr === 'string' && e.stderr.includes('Invalid command')) {
throw new ExpoUpdatesCLIInvalidCommandError(
`The command specified by ${args} was not valid in the \`expo-updates\` CLI.`
);
}
throw e;
}
}
-5
View File
@@ -111,11 +111,6 @@ export default class GitClient extends Client {
return await this.hasUncommittedChangesAsync();
}
public override async showChangedFilesAsync(): Promise<void> {
const gitStatusOutput = await gitStatusAsync({ showUntracked: true });
Log.log(gitStatusOutput);
}
public override async hasUncommittedChangesAsync(): Promise<boolean> {
const changes = await gitStatusAsync({ showUntracked: true });
return changes.length > 0;
+11 -5
View File
@@ -1,13 +1,14 @@
import chalk from 'chalk';
import GitClient from './clients/git';
import GitNoCommitClient from './clients/gitNoCommit';
import NoVcsClient from './clients/noVcs';
import { Client } from './vcs';
const NO_VCS_WARNING = `Using EAS CLI without version control system is not recommended, use this mode only if you know what you are doing.`;
export function resolveVcsClient(requireCommit: boolean = false): Client {
let vcsClient = resolveDefaultVcsClient();
function resolveDefaultVcsClient(): Client {
if (process.env.EAS_NO_VCS) {
if (process.env.NODE_ENV !== 'test') {
// This log might be printed before cli arguments are evaluated,
@@ -18,8 +19,13 @@ export function resolveVcsClient(requireCommit: boolean = false): Client {
}
return new NoVcsClient();
}
if (requireCommit) {
return new GitClient();
}
return new GitNoCommitClient();
}
export function setVcsClient(client: Client): void {
vcsClient = client;
}
export function getVcsClient(): Client {
return vcsClient;
}
-3
View File
@@ -51,9 +51,6 @@ export abstract class Client {
// `commitAsync({ commitAllFiles: false })`
public async showDiffAsync(): Promise<void> {}
/** (optional) print list of changed files */
public async showChangedFilesAsync(): Promise<void> {}
// (optional) returns hash of the last commit
// used for metadata - implementation can be safely skipped
public async getCommitHashAsync(): Promise<string | undefined> {
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "@expo/eas-json",
"description": "A library for interacting with eas.json",
"version": "7.6.1",
"version": "6.0.0",
"author": "Expo <[email protected]>",
"bugs": "https://github.com/expo/eas-cli/issues",
"dependencies": {
"@babel/code-frame": "7.23.5",
"@expo/eas-build-job": "1.0.88",
"@expo/eas-build-job": "1.0.56",
"chalk": "4.1.2",
"env-string": "1.0.1",
"fs-extra": "11.2.0",
+14 -77
View File
@@ -24,19 +24,14 @@
"version": {
"type": "string",
"description": "The compatible versions of EAS CLI with this config",
"examples": [
">=0.54.1"
]
"examples": [">=0.54.1"]
},
"requireCommit": {
"type": "boolean",
"description": "If all changes required to be committed before building or submitting"
},
"appVersionSource": {
"enum": [
"local",
"remote"
],
"enum": ["local", "remote"],
"markdownDescription": "Version policy defines whether version of your app should be based on your local project or values stored on EAS servers (remote).\n\nThis is the configuration required for `eas build:version:set` and works with the `autoIncrement` options per platform.",
"markdownEnumDescriptions": [
"When using local, the `autoIncrement` is based on your local project values.",
@@ -107,10 +102,7 @@
"description": "The name of the build profile that the current one should inherit values from. This value can't be specified per platform."
},
"credentialsSource": {
"enum": [
"remote",
"local"
],
"enum": ["remote", "local"],
"description": "The source of credentials used to sign build artifacts. Learn more: https://docs.expo.dev/app-signing/local-credentials/",
"markdownDescription": "The source of credentials used to sign build artifacts.\n\n- `remote` - if you want to use the credentials managed by EAS.\n- `local` - if you want to provide your own `credentials.json` file. [learn more](https://docs.expo.dev/app-signing/local-credentials/)",
"default": "remote",
@@ -132,10 +124,7 @@
"markdownDescription": "The channel is a name we can give to multiple builds to identify them easily. [Learn more](https://docs.expo.dev/eas-update/how-eas-update-works/)\n\n**This field only applies to the EAS Update service**, if your project still uses Classic Updates then use the [releaseChannel](https://docs.expo.dev/build-reference/eas-json/#releasechannel) field instead."
},
"distribution": {
"enum": [
"internal",
"store"
],
"enum": ["internal", "store"],
"description": "The method of distributing your app. Learn more: https://docs.expo.dev/build/internal-distribution/",
"markdownDescription": "The method of distributing your app.\n\n- `internal` - with this option you'll be able to share your build URLs with anyone, and they will be able to install the builds to their devices straight from the Expo website. When using `internal`, make sure the build produces an APK or IPA file. Otherwise, the shareable URL will be useless. [Learn more](https://docs.expo.dev/build/internal-distribution/)\n- `store` - produces builds for store uploads, your build URLs won't be shareable.",
"markdownEnumDescriptions": [
@@ -214,21 +203,13 @@
"default": "default",
"anyOf": [
{
"enum": [
"default",
"medium",
"large"
]
"enum": ["default", "medium", "large"]
},
{
"type": "string"
}
]
},
"config": {
"description": "Custom workflow file name that will be used to run this build. You can also specify this property on platform level for platform-specific workflows. Learn more: https://docs.expo.dev/custom-builds/get-started/",
"type": "string"
},
"android": {
"$ref": "#/definitions/BuildProfileAndroid"
},
@@ -282,11 +263,7 @@
"default": "default",
"anyOf": [
{
"enum": [
"default",
"medium",
"large"
]
"enum": ["default", "medium", "large"]
},
{
"type": "string"
@@ -298,12 +275,7 @@
"description": "The version of Android NDK."
},
"autoIncrement": {
"enum": [
false,
true,
"versionCode",
"version"
],
"enum": [false, true, "versionCode", "version"],
"description": "Controls how EAS CLI bumps your application build version.",
"markdownDescription": "Controls how EAS CLI bumps your application build version.\n\nAllowed values:\n- `\"version\"` - bumps the patch of `expo.version` (e.g. `1.2.3` -> `1.2.4`).\n- `\"versionCode\"` (or `true`) - bumps `expo.android.versionCode` (e.g. `3` -> `4`).\n- `false` - versions won't be bumped automatically (default)\n\nIn the case of a bare project, it also updates versions in native code. `expo.version` corresponds to `versionName` and `expo.android.versionCode` to `versionCode` in the `build.gradle`. Google Play uses these values to identify the app build, `versionName` is the version visible to users, whereas `versionCode` defines the version number. The combination of those needs to be unique, so you can bump either of them.\n\nThis feature is not intended for use with dynamic configuration (app.config.js). EAS CLI will throw an error if you don't use app.json.",
"default": false,
@@ -315,10 +287,7 @@
]
},
"buildType": {
"enum": [
"app-bundle",
"apk"
],
"enum": ["app-bundle", "apk"],
"description": "Type of the artifact you want to build.",
"markdownDescription": "Type of the artifact you want to build. It controls what Gradle task will be used, can be overridden by `gradleCommand` or `developmentClient: true` option.\n- `app-bundle` - `:app:bundleRelease`\n- `apk` - `:app:assembleRelease`",
"markdownEnumDescriptions": [
@@ -342,10 +311,6 @@
"description": "[DEPRECATED] Use `applicationArchivePath` instead. Path (or pattern) where EAS Build is going to look for the build artifacts. See: https://github.com/mrmlnc/fast-glob#pattern-syntax",
"markdownDescription": "[DEPRECATED] Use `applicationArchivePath` instead. Path (or pattern) where EAS Build is going to look for the build artifacts. EAS Build uses the `fast-glob` npm package for pattern matching ([see their README to learn more about the syntax you can use](https://github.com/mrmlnc/fast-glob#pattern-syntax)).",
"default": "android/app/build/outputs/**/*.{apk,aab}"
},
"config": {
"description": "Custom workflow file name that will be used to run this Android build. You can also specify this property on profile levle for platform-agnostic workflows. Learn more: https://docs.expo.dev/custom-builds/get-started/",
"type": "string"
}
}
},
@@ -365,22 +330,14 @@
"default": false
},
"enterpriseProvisioning": {
"enum": [
"universal",
"adhoc"
],
"enum": ["universal", "adhoc"],
"markdownDescription": "Provisioning method used for `\"distribution\": \"internal\"` when you have an Apple account with Apple Developer Enterprise Program membership.\n\nYou can choose if you want to use `adhoc` or `universal` provisioning. The latter is recommended as it does not require you to register each individual device. If you don't provide this option and you still authenticate with an enterprise team, you'll be prompted which provisioning method to use.",
"markdownEnumDescriptions": [
"Recommended as it does not require you to register each individual device"
]
},
"autoIncrement": {
"enum": [
false,
true,
"buildNumber",
"version"
],
"enum": [false, true, "buildNumber", "version"],
"description": "Controls how EAS CLI bumps your application build version.",
"markdownDescription": "Controls how EAS CLI bumps your application build version.\n\nAllowed values:\n\n- `\"version\"` - bumps the patch of `expo.version` (e.g. `1.2.3` -> `1.2.4`).\n- `\"buildNumber\"` (or `true`) - bumps the last component of `expo.ios.buildNumber` (e.g. `1.2.3.39` -> `1.2.3.40`).\n- `false` - versions won't be bumped automatically (default)\n\nIn the case of a bare project, it also updates versions in native code. `expo.version` corresponds to `CFBundleShortVersionString` and `expo.ios.buildNumber` to `CFBundleVersion` in the `Info.plist`. The App Store is using those values to identify the app build, `CFBundleShortVersionString` is the version visible to users, whereas `CFBundleVersion` defines the build number. The combination of those needs to be unique, so you can bump either of them.\n\nThis feature is not intended for use with dynamic configuration (app.config.js). EAS CLI will throw an error if you don't use app.json.",
"default": false,
@@ -400,7 +357,6 @@
"enum": [
"default",
"latest",
"macos-ventura-13.6-xcode-15.2",
"macos-ventura-13.6-xcode-15.1",
"macos-ventura-13.6-xcode-15.0",
"macos-ventura-13.4-xcode-14.3.1",
@@ -411,7 +367,7 @@
],
"markdownEnumDescriptions": [
"`macos-ventura-13.4-xcode-14.3.1`",
"`macos-ventura-13.6-xcode-15.2`"
"`macos-ventura-13.6-xcode-15.1`"
]
},
{
@@ -435,12 +391,7 @@
"default": "default",
"anyOf": [
{
"enum": [
"default",
"medium",
"large",
"m-medium"
]
"enum": ["default", "medium", "large", "m-medium"]
},
{
"type": "string"
@@ -481,10 +432,6 @@
"type": "string",
"description": "[DEPRECATED] Use `applicationArchivePath` instead. Path (or pattern) where EAS Build is going to look for the build artifacts. See: https://github.com/mrmlnc/fast-glob#pattern-syntax",
"markdownDescription": "[DEPRECATED] Use `applicationArchivePath` instead. Path (or pattern) where EAS Build is going to look for the build artifacts.\n\nEAS Build uses the `fast-glob` npm package for pattern matching, ([See their README to learn more about the syntax you can use](https://github.com/mrmlnc/fast-glob#pattern-syntax)).\n\nYou should modify that path only if you are using a custom `Gymfile`.\n\nThe default is `ios/build/Build/Products/*-iphonesimulator/*.app` when building for simulator and `ios/build/*.ipa` in other cases."
},
"config": {
"description": "Custom workflow file name that will be used to run this iOS build. You can also specify this property on profile levle for platform-agnostic workflows. Learn more: https://docs.expo.dev/custom-builds/get-started/",
"type": "string"
}
}
},
@@ -524,12 +471,7 @@
"markdownDescription": "Path to the JSON file with service account key used to authenticate with Google Play. [Learn more](https://expo.fyi/creating-google-service-account)"
},
"track": {
"enum": [
"beta",
"alpha",
"internal",
"production"
],
"enum": ["beta", "alpha", "internal", "production"],
"description": "The track of the application to use. Learn more: https://support.google.com/googleplay/android-developer/answer/9859348?hl=en",
"markdownDescription": "The [track of the application](https://support.google.com/googleplay/android-developer/answer/9859348?hl=en) to use.",
"markdownEnumDescriptions": [
@@ -540,12 +482,7 @@
]
},
"releaseStatus": {
"enum": [
"draft",
"inProgress",
"halted",
"completed"
],
"enum": ["draft", "inProgress", "halted", "completed"],
"description": "The status of a release. Learn more: https://developers.google.com/android-publisher/api-ref/rest/v3/edits.tracks",
"markdownDescription": "The status of a release. [Learn more](https://developers.google.com/android-publisher/api-ref/rest/v3/edits.tracks)",
"enumDescriptions": [
@@ -107,10 +107,10 @@ test('ios config with all required values', async () => {
ios: {
appleId: '[email protected]',
ascAppId: '1223423523',
appleTeamId: 'AB32CZE81F',
appleTeamId: 'QWERTY',
ascApiKeyPath: './path-ABCD.p8',
ascApiKeyIssuerId: 'b4d78f58-48c6-4f2c-96cb-94d8cd76970a',
ascApiKeyId: 'AB32CZE81F',
ascApiKeyIssuerId: 'abc-123-def-456',
ascApiKeyId: 'ABCD',
},
},
},
@@ -121,11 +121,11 @@ test('ios config with all required values', async () => {
expect(iosProfile).toEqual({
appleId: '[email protected]',
appleTeamId: 'AB32CZE81F',
appleTeamId: 'QWERTY',
ascAppId: '1223423523',
ascApiKeyPath: './path-ABCD.p8',
ascApiKeyIssuerId: 'b4d78f58-48c6-4f2c-96cb-94d8cd76970a',
ascApiKeyId: 'AB32CZE81F',
ascApiKeyIssuerId: 'abc-123-def-456',
ascApiKeyId: 'ABCD',
language: 'en-US',
});
});
@@ -137,7 +137,7 @@ test('ios config with ascApiKey fields set to env var', async () => {
ios: {
appleId: '[email protected]',
ascAppId: '1223423523',
appleTeamId: 'AB32CZE81F',
appleTeamId: 'QWERTY',
ascApiKeyPath: '$ASC_API_KEY_PATH',
ascApiKeyIssuerId: '$ASC_API_KEY_ISSUER_ID',
ascApiKeyId: '$ASC_API_KEY_ID',
@@ -148,18 +148,18 @@ test('ios config with ascApiKey fields set to env var', async () => {
try {
process.env.ASC_API_KEY_PATH = './path-ABCD.p8';
process.env.ASC_API_KEY_ISSUER_ID = 'b4d78f58-48c6-4f2c-96cb-94d8cd76970a';
process.env.ASC_API_KEY_ID = 'AB32CZE81F';
process.env.ASC_API_KEY_ISSUER_ID = 'abc-123-def-456';
process.env.ASC_API_KEY_ID = 'ABCD';
const accessor = EasJsonAccessor.fromProjectPath('/project');
const iosProfile = await EasJsonUtils.getSubmitProfileAsync(accessor, Platform.IOS, 'release');
expect(iosProfile).toEqual({
appleId: '[email protected]',
ascAppId: '1223423523',
appleTeamId: 'AB32CZE81F',
appleTeamId: 'QWERTY',
ascApiKeyPath: './path-ABCD.p8',
ascApiKeyIssuerId: 'b4d78f58-48c6-4f2c-96cb-94d8cd76970a',
ascApiKeyId: 'AB32CZE81F',
ascApiKeyIssuerId: 'abc-123-def-456',
ascApiKeyId: 'ABCD',
language: 'en-US',
});
} finally {
@@ -176,16 +176,16 @@ test('valid profile extending other profile', async () => {
ios: {
appleId: '[email protected]',
ascAppId: '1223423523',
appleTeamId: 'AB32CZE81F',
appleTeamId: 'QWERTY',
},
},
extension: {
extends: 'base',
ios: {
appleTeamId: 'AB32CZE81F',
appleTeamId: 'ABCDEF',
ascApiKeyPath: './path-ABCD.p8',
ascApiKeyIssuerId: '2af70a7a-2ac5-44d4-924e-ae97a7ca9333',
ascApiKeyId: 'AB32CZE81F',
ascApiKeyIssuerId: 'abc-123-def-456',
ascApiKeyId: 'ABCD',
},
},
},
@@ -202,134 +202,19 @@ test('valid profile extending other profile', async () => {
language: 'en-US',
appleId: '[email protected]',
ascAppId: '1223423523',
appleTeamId: 'AB32CZE81F',
appleTeamId: 'QWERTY',
});
expect(extendedProfile).toEqual({
language: 'en-US',
appleId: '[email protected]',
ascAppId: '1223423523',
appleTeamId: 'AB32CZE81F',
appleTeamId: 'ABCDEF',
ascApiKeyPath: './path-ABCD.p8',
ascApiKeyIssuerId: '2af70a7a-2ac5-44d4-924e-ae97a7ca9333',
ascApiKeyId: 'AB32CZE81F',
ascApiKeyIssuerId: 'abc-123-def-456',
ascApiKeyId: 'ABCD',
});
});
test('ios config with with invalid appleId', async () => {
await fs.writeJson('/project/eas.json', {
submit: {
release: {
ios: {
appleId: '| /bin/bash echo "hello"',
ascAppId: '1223423523',
appleTeamId: 'AB32CZE81F',
ascApiKeyPath: './path-ABCD.p8',
ascApiKeyIssuerId: '2af70a7a-2ac5-44d4-924e-ae97a7ca9333',
ascApiKeyId: 'AB32CZE81F',
},
},
},
});
const accessor = EasJsonAccessor.fromProjectPath('/project');
const promise = EasJsonUtils.getSubmitProfileAsync(accessor, Platform.IOS, 'release');
await expect(promise).rejects.toThrow(
'Invalid Apple ID was specified. It should be a valid email address. Example: "[email protected]".'
);
});
test('ios config with with invalid ascAppId', async () => {
await fs.writeJson('/project/eas.json', {
submit: {
release: {
ios: {
appleId: '[email protected]',
ascAppId: 'othervalue',
appleTeamId: 'AB32CZE81F',
ascApiKeyPath: './path-ABCD.p8',
ascApiKeyIssuerId: '2af70a7a-2ac5-44d4-924e-ae97a7ca9333',
ascApiKeyId: 'AB32CZE81F',
},
},
},
});
const accessor = EasJsonAccessor.fromProjectPath('/project');
const promise = EasJsonUtils.getSubmitProfileAsync(accessor, Platform.IOS, 'release');
await expect(promise).rejects.toThrow(
'Invalid Apple App Store Connect App ID ("ascAppId") was specified. It should consist only of digits. Example: "1234567891". Learn more: https://expo.fyi/asc-app-id.'
);
});
test('ios config with with invalid appleTeamId', async () => {
await fs.writeJson('/project/eas.json', {
submit: {
release: {
ios: {
appleId: '[email protected]',
ascAppId: '1223423523',
appleTeamId: 'ls -la',
ascApiKeyPath: './path-ABCD.p8',
ascApiKeyIssuerId: '2af70a7a-2ac5-44d4-924e-ae97a7ca9333',
ascApiKeyId: 'AB32CZE81F',
},
},
},
});
const accessor = EasJsonAccessor.fromProjectPath('/project');
const promise = EasJsonUtils.getSubmitProfileAsync(accessor, Platform.IOS, 'release');
await expect(promise).rejects.toThrow(
'Invalid Apple Team ID was specified. It should consist of 10 uppercase letters or digits. Example: "AB32CZE81F".'
);
});
test('ios config with with invalid ascApiKeyIssuerId', async () => {
await fs.writeJson('/project/eas.json', {
submit: {
release: {
ios: {
appleId: '[email protected]',
ascAppId: '1223423523',
appleTeamId: 'AB32CZE81F',
ascApiKeyPath: './path-ABCD.p8',
ascApiKeyIssuerId: 'notanuuid',
ascApiKeyId: 'AB32CZE81F',
},
},
},
});
const accessor = EasJsonAccessor.fromProjectPath('/project');
const promise = EasJsonUtils.getSubmitProfileAsync(accessor, Platform.IOS, 'release');
await expect(promise).rejects.toThrow(
'Invalid Apple App Store Connect API Key Issuer ID ("ascApiKeyIssuerId") was specified. It should be a valid UUID. Example: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx". Learn more: https://expo.fyi/creating-asc-api-key.'
);
});
test('ios config with with invalid ascApiKeyId', async () => {
await fs.writeJson('/project/eas.json', {
submit: {
release: {
ios: {
appleId: '[email protected]',
ascAppId: '1223423523',
appleTeamId: 'AB32CZE81F',
ascApiKeyPath: './path-ABCD.p8',
ascApiKeyIssuerId: 'b4d78f58-48c6-4f2c-96cb-94d8cd76970a',
ascApiKeyId: 'wrong value',
},
},
},
});
const accessor = EasJsonAccessor.fromProjectPath('/project');
const promise = EasJsonUtils.getSubmitProfileAsync(accessor, Platform.IOS, 'release');
await expect(promise).rejects.toThrow(
`Invalid Apple App Store Connect API Key ID ("ascApiKeyId") was specified. It should consist of uppercase letters or digits. Example: "AB32CZE81F". Learn more: https://expo.fyi/creating-asc-api-key.`
);
});
test('get profile names', async () => {
await fs.writeJson('/project/eas.json', {
submit: {
+2 -2
View File
@@ -1,7 +1,7 @@
import Joi from 'joi';
import { BuildProfileSchema } from './build/schema';
import { UnresolvedSubmitProfileSchema } from './submit/schema';
import { SubmitProfileSchema } from './submit/schema';
import { AppVersionSource } from './types';
export const EasJsonSchema = Joi.object({
@@ -12,5 +12,5 @@ export const EasJsonSchema = Joi.object({
promptToConfigurePushNotifications: Joi.boolean(),
}),
build: Joi.object().pattern(Joi.string(), BuildProfileSchema),
submit: Joi.object().pattern(Joi.string(), UnresolvedSubmitProfileSchema),
submit: Joi.object().pattern(Joi.string(), SubmitProfileSchema),
});
+2 -2
View File
@@ -1,7 +1,7 @@
import { Platform } from '@expo/eas-build-job';
import envString from 'env-string';
import { AndroidSubmitProfileSchema, ResolvedIosSubmitProfileSchema } from './schema';
import { AndroidSubmitProfileSchema, IosSubmitProfileSchema } from './schema';
import {
AndroidSubmitProfileFieldsToEvaluate,
IosSubmitProfileFieldsToEvaluate,
@@ -99,7 +99,7 @@ function mergeProfiles<T extends Platform>(
export function getDefaultProfile<T extends Platform>(platform: T): SubmitProfile<T> {
const Schema =
platform === Platform.ANDROID ? AndroidSubmitProfileSchema : ResolvedIosSubmitProfileSchema;
platform === Platform.ANDROID ? AndroidSubmitProfileSchema : IosSubmitProfileSchema;
return Schema.validate({}, { allowUnknown: false, abortEarly: false, convert: true }).value;
}
+3 -43
View File
@@ -19,9 +19,7 @@ export const AndroidSubmitProfileSchema = Joi.object({
}),
});
// it is less strict submission schema allowing for magic syntax like "$ASC_API_KEY_PATH"
// to read value from environment variable later on
export const UnresolvedIosSubmitProfileSchema = Joi.object({
export const IosSubmitProfileSchema = Joi.object({
ascApiKeyPath: Joi.string(),
ascApiKeyId: Joi.string(),
ascApiKeyIssuerId: Joi.string(),
@@ -36,46 +34,8 @@ export const UnresolvedIosSubmitProfileSchema = Joi.object({
metadataPath: Joi.string(),
});
// more strict version after resolving all of the values
export const ResolvedIosSubmitProfileSchema = Joi.object({
ascApiKeyPath: Joi.string(),
ascApiKeyId: Joi.string()
.regex(/^[\dA-Z]+$/)
.message(
'Invalid Apple App Store Connect API Key ID ("ascApiKeyId") was specified. It should consist of uppercase letters or digits. Example: "AB32CZE81F". Learn more: https://expo.fyi/creating-asc-api-key.'
)
.max(30), // I didn't find any docs about it, but all of the ones I've seen are 10 characters long so 30 characters limit should be enough
ascApiKeyIssuerId: Joi.string()
.uuid() // All of the issuer IDs I've seen are UUIDs, but again, I didn't find any docs about it
.message(
'Invalid Apple App Store Connect API Key Issuer ID ("ascApiKeyIssuerId") was specified. It should be a valid UUID. Example: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx". Learn more: https://expo.fyi/creating-asc-api-key.'
),
appleId: Joi.string()
.email()
.message(
'Invalid Apple ID was specified. It should be a valid email address. Example: "[email protected]".'
),
ascAppId: Joi.string()
.regex(/^\d+$/)
.message(
'Invalid Apple App Store Connect App ID ("ascAppId") was specified. It should consist only of digits. Example: "1234567891". Learn more: https://expo.fyi/asc-app-id.'
)
.max(30), // I didn't find any docs about it, but the longest app ID I've seen is 10 digits long so 30 characters limit should be enough
appleTeamId: Joi.string()
.regex(/^[\dA-Z]{10}$/) // Apple says that it always has to be 10 characters long https://developer.apple.com/help/account/manage-your-team/locate-your-team-id/
.message(
'Invalid Apple Team ID was specified. It should consist of 10 uppercase letters or digits. Example: "AB32CZE81F".'
),
sku: Joi.string(),
language: Joi.string().default('en-US'),
companyName: Joi.string(),
appName: Joi.string(),
bundleIdentifier: Joi.string(),
metadataPath: Joi.string(),
});
export const UnresolvedSubmitProfileSchema = Joi.object({
export const SubmitProfileSchema = Joi.object({
extends: Joi.string(),
android: AndroidSubmitProfileSchema,
ios: UnresolvedIosSubmitProfileSchema,
ios: IosSubmitProfileSchema,
});
Loaded 100 of 102 files, more files were not shown because too many files have changed in this diff. Show more