Compare commits

..
Author SHA1 Message Date
Brent Vatne 3ac45f08ba v7.4.0 2024-03-09 18:50:50 -08:00
Brent Vatne 73ba19de66 [eas-cli] Bump @expo/apple-utils 2024-03-09 18:50:16 -08:00
Will Schurman ef6623cd15 [eas-cli] Use new expo-updates configuration:syncnative for versioned native sync (#2269) 2024-03-08 14:27:12 -08:00
Will Schurman d78917b947 Revert "Revert "[eas-cli] Use expo-updates runtime version CLI to generate runtime ve…" (#2264)" (#2265) 2024-03-07 08:55:53 -08:00
Will Schurman 2b59a5e2ee Revert "[eas-cli] Use expo-updates runtime version CLI to generate runtime ve…" (#2264)
This reverts commit 561e3bbb5a.
2024-03-06 09:13:20 -08:00
Expo Bot e6465cd3e5 Upgrade eas-build dependencies (#2259)
* Upgrade eas-build dependencies

* update CHANGELOG.md
2024-03-05 15:07:24 +01:00
Will Schurman 561e3bbb5a [eas-cli] Use expo-updates runtime version CLI to generate runtime versions (#2251) 2024-02-28 09:27:14 -08:00
dependabot[bot] 64a6e3a0f7 Bump es5-ext from 0.10.53 to 0.10.63 (#2255)
Bumps [es5-ext](https://github.com/medikoo/es5-ext) from 0.10.53 to 0.10.63.
- [Release notes](https://github.com/medikoo/es5-ext/releases)
- [Changelog](https://github.com/medikoo/es5-ext/blob/main/CHANGELOG.md)
- [Commits](https://github.com/medikoo/es5-ext/compare/v0.10.53...v0.10.63)

---
updated-dependencies:
- dependency-name: es5-ext
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-27 09:07:36 +01:00
Will Schurman 33c965b236 [vscode] Include src/**/build directories in search and replace (#2250) 2024-02-26 10:19:35 -08:00
Expo Bot 831e69e5c6 Upgrade eas-build dependencies (#2253)
* Upgrade eas-build dependencies

* update CHANGELOG.md
2024-02-26 17:09:09 +01:00
Stanisław Chmiela 7d47060b12 Add config property to eas.schema.json (#2248)
# Why

We want users to feel like they're adding something we support.

# How

Added `config` property to build profile level and platform-specific profile properties levels.

Also prettified the file according to my JSON Tools VS Code extension. Let me know if it should be deprettified.

# Test Plan

None.
2024-02-23 17:24:35 +01:00
Will Schurman b6b22b79c3 [eas-cli] Fix expo-updates package version detection for canaries (#2243) 2024-02-22 08:14:24 -08:00
Expo Bot 6770cd99c9 Upgrade eas-build dependencies (#2240)
* Upgrade eas-build dependencies

* update CHANGELOG.md
2024-02-21 11:48:12 +01:00
dependabot[bot] 704745b829 Bump ip from 1.1.5 to 1.1.9 (#2238)
Bumps [ip](https://github.com/indutny/node-ip) from 1.1.5 to 1.1.9.
- [Commits](https://github.com/indutny/node-ip/compare/v1.1.5...v1.1.9)

---
updated-dependencies:
- dependency-name: ip
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-20 21:37:49 +01:00
Quinlan Jung 3780e2ae1c [eas-cli] reword the update configure instruction (#2234)
* [eas-cli] reword the update configure instruction

* nits

* update CHANGELOG.md
2024-02-20 10:58:11 -07:00
Expo Bot e93854d039 Upgrade eas-build dependencies (#2237)
⬆️ Upgrades [`eas-build`](https://github.com/expo/eas-build) dependencies.
2024-02-20 14:23:24 +01:00
Expo CI 89354f5932 update CHANGELOG.md 2024-02-19 16:25:41 +00:00
Szymon Dziedzic a074ce0cff v7.3.0 2024-02-19 17:18:11 +01:00
Szymon Dziedzic 31f583442a upgrade eas-cli-local-build-plugin to 1.0.71 2024-02-19 17:18:03 +01:00
Radosław Krzemień 9bf1f383e5 [eas-cli] [ENG-11310] Don't require expo on fresh react-native project (#2235)
* [eas-cli] Don't require expo

Do not require expo to be installed and configured for a fresh react-native project

See: https://linear.app/expo/issue/ENG-11310/fix-warnings-errors-that-come-up-when-adding-eas-to-a-react-native-cli

* update CHANGELOG.md

* [eas-cli] Throw other errors

Forgot to rethrow other types of errors

See: https://linear.app/expo/issue/ENG-11310/fix-warnings-errors-that-come-up-when-adding-eas-to-a-react-native-cli
2024-02-19 16:44:07 +01:00
Will Schurman e157473f41 [eas-cli] fix expo-updates fingerprinting during update (#2231) 2024-02-16 14:09:40 -08:00
Expo Bot ba87bb6e29 Upgrade eas-build dependencies (#2230)
* Upgrade eas-build dependencies

* update CHANGELOG.md
2024-02-16 11:12:42 +01:00
Expo Bot efd9213fab Upgrade eas-build dependencies (#2229) 2024-02-14 17:33:56 +01:00
Expo CI a3d9bc0eca update CHANGELOG.md 2024-02-11 04:48:40 +00:00
Brent Vatne 39dc6299d2 v7.2.0 2024-02-10 20:42:08 -08:00
Brent Vatne 37573bed50 Bump @xpo/apple-utils 2024-02-10 20:40:58 -08:00
Will Schurman 2e49f6348e Revert "feat(eas-cli): expose expo export dev flag as an option in eas update (#2050)" (#2214) 2024-02-08 12:38:16 -08:00
Expo BotandSzymon Dziedzic 3a7ddbd025 Upgrade eas-build dependencies (#2223)
* Upgrade eas-build dependencies

* update CHANGELOG.md

* fix type errors

---------

Co-authored-by: Szymon Dziedzic <[email protected]>
2024-02-08 10:40:58 +01:00
Chris Walter a5c1100ce1 [fcmv1] Manage FCM V1 Google Service Account Key in CLI (#2197)
* [fcmv1] Manage FCM V1 Google Service Account Key in CLI

# Why
NOTE: DO NOT LAND THIS UNTIL GRAPHQL CHANGES LAND IN WWW

We're adding support for FCM V1 credentials, as Google is shutting down
the FCM Legacy API for sending Android notifications in June.

# How
Add new prompts and refactor existing prompts to match this schematic:

# Test Plan
Verified all functionality e2e:

* update CHANGELOG.md
2024-02-07 15:26:56 -08:00
Expo CI 0b71812694 update CHANGELOG.md 2024-02-07 12:34:16 +00:00
Stanisław Chmiela caf2403dfd v7.1.3 2024-02-07 13:24:16 +01:00
Expo Bot 09fe5dd1a3 Upgrade eas-build dependencies (#2220) 2024-02-07 12:39:31 +01:00
Stanisław Chmiela 048460f323 Add workflow for bumping eas-build dependencies (#2216)
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->

# Why

It is currently not possible to use `if: ${ always() }` in Custom Build workflows due to outdated `@expo/steps` dependency.

# How

Added a GitHub workflow, similar to the one we have in `turtle-v2`, which will automatically upgrade all dependencies from the `eas-build` repo.

# Test Plan

https://github.com/expo/eas-cli/pull/2220
2024-02-07 12:39:19 +01:00
Radosław Krzemień 69b0edae8d [eas-cli] [ENG-9957] Reapply changes after fixing query in www (#2209)
* Revert "Revert "[eas-cli] [ENG-9957] Don't overwrite distribution for simulator build…" (#2207)"

This reverts commit a6e281b6

* [eas-cli] Generate schema

Re-generated gql schema

See: https://linear.app/expo/issue/ENG-11247/fix-console-output-when-creating-asc-key
2024-02-05 11:37:39 +01:00
Szymon Dziedzic 9ee9ea39bb [ci] auto update EAS CLI version used on production for builds triggered using GitHub trigger (#2211)
* [ci] add update eas cli used on production for builds triggered with GitHub trigger once new version is published

* remove unnecessary docs from releasing
2024-02-01 23:26:17 +01:00
Radosław Krzemień 204a8b7eb4 [eas-cli] [ENG-11247] Remove duplicate log (#2208)
* [eas-cli] Remove duplicate log

Information about App Store Connect API key being created was displayed twice to the user. This removes the duplicate

See: https://linear.app/expo/issue/ENG-11247/fix-console-output-when-creating-asc-key

* update CHANGELOG.md
2024-02-01 12:28:45 +01:00
Szymon Dziedzic a6e281b6c8 Revert "[eas-cli] [ENG-9957] Don't overwrite distribution for simulator build…" (#2207)
This reverts commit 315b5b23f8.
2024-01-31 21:06:37 +01:00
Radosław Krzemień 315b5b23f8 [eas-cli] [ENG-9957] Don't overwrite distribution for simulator builds (#2073)
* [eas-cli] Update dependencies

Updated eas-build-job to new version

See: https://linear.app/expo/issue/ENG-9957/fix-internal-distribution-pages-for-simulator-builds

* [eas-cli] Don't overwrite distribution

Stops overwriting distribution type for simulator builds, and sets simulator field in metadata instead

See: https://linear.app/expo/issue/ENG-9957/fix-internal-distribution-pages-for-simulator-builds

* [eas-cli] Merge main

Merged changes from main branch

See: https://linear.app/expo/issue/ENG-9957/fix-internal-distribution-pages-for-simulator-builds

* [eas-cli] Check for simulator flag

Updated build:run command to use simulator flag instead of overwritten distribution type

See: https://linear.app/expo/issue/ENG-9957/fix-internal-distribution-pages-for-simulator-builds

* [eas-cli] Update schema

Update graphql schema with simulator fields

See: https://linear.app/expo/issue/ENG-9957/fix-internal-distribution-pages-for-simulator-builds

* [eas-cli] Add flag

Add simulator flag to build:list command

See: https://linear.app/expo/issue/ENG-9957/fix-internal-distribution-pages-for-simulator-builds

* [eas-cli] Fix check

Fixed check function with correct field name

See: https://linear.app/expo/issue/ENG-9957/fix-internal-distribution-pages-for-simulator-builds

* [eas-cli] Fix tests

Fixed failing tests after BuildFragment structure changed

See: https://linear.app/expo/issue/ENG-9957/fix-internal-distribution-pages-for-simulator-builds

* [eas-cli] Add warning

Added warning to build:list command that the distribution=simulator is deprecated

See: https://linear.app/expo/issue/ENG-9957/fix-internal-distribution-pages-for-simulator-builds

* [eas-cli] Add description

Added description to the new simulator flag

See: https://linear.app/expo/issue/ENG-9957/fix-internal-distribution-pages-for-simulator-builds

* [eas-cli] Add validation

Added validation so the simulator flag can only be used with --platofrm=ios

See: https://linear.app/expo/issue/ENG-9957/fix-internal-distribution-pages-for-simulator-builds

* [eas-cli] Change message

Updated the warning displayed when using deprecated --distribution=simulator flag value

See: https://linear.app/expo/issue/ENG-9957/fix-internal-distribution-pages-for-simulator-builds

* [eas-cli] Replace string

Replaced hardcoded string with variable

See: https://linear.app/expo/issue/ENG-9957/fix-internal-distribution-pages-for-simulator-builds

* [eas-cli] Remove redundant check

Removed no longer necessary check for simulator build

See: https://linear.app/expo/issue/ENG-9957/fix-internal-distribution-pages-for-simulator-builds

* [eas-cli] Update schema

Updated graphql schema after recent changes

See: https://linear.app/expo/issue/ENG-9957/fix-internal-distribution-pages-for-simulator-builds

* [eas-cli] Update schema

Updated graphql schema after recent changes

See: https://linear.app/expo/issue/ENG-9957/fix-internal-distribution-pages-for-simulator-builds

* update CHANGELOG.md

* [eas-cli] Update schema

Updated graphql schema after recent changes

See: https://linear.app/expo/issue/ENG-9957/fix-internal-distribution-pages-for-simulator-builds
2024-01-31 17:21:05 +01:00
Szymon Dziedzic ceb561a4af add sjchmiela as codeowner (#2205) 2024-01-31 15:23:00 +01:00
Expo CI 63743cae65 update CHANGELOG.md 2024-01-30 10:26:13 +00:00
Szymon Dziedzic e8e5eb622c v7.1.2 2024-01-30 11:19:50 +01:00
Szymon DziedzicandStanisław Chmiela fe8f1b32b3 Revert "Revert "[eas-json] validate EAS Submit inputs better"" (#2202)
* Revert "Revert "[eas-json] validate EAS Submit inputs better""

* make validation constraints more loose where necessary

* update CHANGELOG.md

* fix message

* Apply suggestions from code review

Co-authored-by: Stanisław Chmiela <[email protected]>

* apply suggested changes

---------

Co-authored-by: Stanisław Chmiela <[email protected]>
2024-01-30 11:13:41 +01:00
Expo CI 3a1e5298a4 update CHANGELOG.md 2024-01-26 20:19:03 +00:00
Szymon Dziedzic 92c1256e8b v7.1.1 2024-01-26 21:11:12 +01:00
Szymon Dziedzic 61543c7983 Revert "[eas-json] validate EAS Submit inputs better" (#2200)
* Revert "[eas-json] validate EAS Submit inputs better"

* revert changelog revert

* update CHANGELOG.md
2024-01-26 21:03:43 +01:00
Expo CI 62d149ae60 update CHANGELOG.md 2024-01-26 09:58:59 +00:00
Szymon Dziedzic bbf14e2ee8 v7.1.0 2024-01-26 10:53:35 +01:00
Szymon DziedzicandStanisław Chmiela 126c5627eb [eas-json] validate EAS Submit inputs better (#2198)
* [eas-json] sanitize EAS Submit inputs better

* add link to docs

* update CHANGELOG.md

* validate app specific password

* use Joi schema for validation

* fix typo

* minor improvements

* Update packages/eas-cli/src/submit/ios/__tests__/IosSubmitCommand-test.ts

Co-authored-by: Stanisław Chmiela <[email protected]>

* make uuid validation less strict

* apply suggested changes

* fix tests

---------

Co-authored-by: Stanisław Chmiela <[email protected]>
2024-01-26 10:48:01 +01:00
Will Schurman b5f2f5286a [eas-cli] Support requireCommit for EAS Update (#2196) 2024-01-22 10:38:13 -08:00
Will Schurman 8ea05793dd [eas-cli] Remove support for classic updates release channel in 50+ (#2189) 2024-01-19 10:53:52 -08:00
Expo CI 02c8dcaa5b update CHANGELOG.md 2024-01-19 14:57:46 +00:00
Szymon Dziedzic fe1a1f14d1 v7.0.0 2024-01-19 15:51:27 +01:00
Szymon Dziedzic df7b18ca03 upgrade eas-cli-local-build-plugin to 1.0.60 2024-01-19 15:46:42 +01:00
Quinlan Jung 41142a9486 [eas-cli] Revert "[1/1][eas-cli] generate eas-update-metadata.json on publish … (#2187)
* Revert "[1/1][eas-cli] generate eas-update-metadata.json  on publish (#2158)"

This reverts commit 183fe8712b.

* lint

* update CHANGELOG.md
2024-01-18 13:59:19 -08:00
Quinlan Jung 72c28d4259 [eas-cli] use branch mapping utility fn (#2186)
* [eas-cli] use branch mapping utility fn

* update CHANGELOG.md
2024-01-18 13:58:43 -08:00
Expo CI da42962151 update CHANGELOG.md 2024-01-18 21:28:12 +00:00
Brent Vatne bbebe90876 v6.1.0 2024-01-18 13:21:18 -08:00
Will Schurman ea57d6383a [eas-cli] Upgrade packages from the expo/expo repo (#2145) 2024-01-18 11:01:00 -08:00
Szymon Dziedzic f5a99cea6b [ENG-11092][eas-json] update eas.schema.json to add support for Xcode 15.2 image (#2184)
* [eas-json] update `eas.schema.json` to add support for Xcode 15.2 image

* update CHANGELOG.md
2024-01-18 17:57:31 +01:00
82 changed files with 1948 additions and 703 deletions

No files matched your search

+7 -1
View File
@@ -152,7 +152,13 @@ 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
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 }}
- 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
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
release-changelog:
@@ -0,0 +1,81 @@
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
@@ -0,0 +1,10 @@
{
"eslint.enable": true,
"search.exclude": {
"**/node_modules": true,
"**/bower_components": true,
"**/*.code-search": true,
"**/src/**/build/**": false,
"**/src/build/**": false,
}
}
+94 -3
View File
@@ -8,17 +8,108 @@ This is the log of notable changes to EAS CLI and related packages.
### 🎉 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))
- 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
### 🧹 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))
### 🧹 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))
- Prompt user to map channel on update if unmapped. ([#2185](https://github.com/expo/eas-cli/pull/2185) by [@quinlanj](https://github.com/quinlanj))
- 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))
## [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
* @szdziedzic @khamilowicz @sjchmiela
packages/eas-cli/src/build @szdziedzic @khamilowicz
packages/eas-cli/src/commands/build @szdziedzic @khamilowicz
packages/eas-cli/src/build @szdziedzic @khamilowicz @sjchmiela
packages/eas-cli/src/commands/build @szdziedzic @khamilowicz @sjchmiela
packages/eas-cli/src/submit @szdziedzic @khamilowicz
packages/eas-cli/src/commands/submit.ts @szdziedzic @khamilowicz
packages/eas-cli/src/submit @szdziedzic @khamilowicz @sjchmiela
packages/eas-cli/src/commands/submit.ts @szdziedzic @khamilowicz @sjchmiela
packages/eas-cli/src/update @EvanBacon @byCedric @wschurman
packages/eas-cli/src/commands/update @EvanBacon @byCedric @wschurman
@@ -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
packages/eas-json @szdziedzic @khamilowicz @sjchmiela
-4
View File
@@ -12,7 +12,3 @@ 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": "6.0.0",
"version": "7.4.0",
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
}
+87 -63
View File
@@ -68,6 +68,7 @@ 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)
@@ -135,7 +136,7 @@ ALIASES
$ eas login
```
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/account/login.ts)_
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/account/login.ts)_
## `eas account:logout`
@@ -152,7 +153,7 @@ ALIASES
$ eas logout
```
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/account/logout.ts)_
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/account/logout.ts)_
## `eas account:view`
@@ -169,7 +170,7 @@ ALIASES
$ eas whoami
```
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/account/view.ts)_
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/account/view.ts)_
## `eas analytics [STATUS]`
@@ -183,7 +184,7 @@ DESCRIPTION
display or change analytics settings
```
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/analytics.ts)_
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/analytics.ts)_
## `eas autocomplete [SHELL]`
@@ -235,7 +236,7 @@ DESCRIPTION
create a branch
```
_See code: [src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/branch/create.ts)_
_See code: [src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/branch/create.ts)_
## `eas branch:delete [NAME]`
@@ -256,7 +257,7 @@ DESCRIPTION
delete a branch
```
_See code: [src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/branch/delete.ts)_
_See code: [src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/branch/delete.ts)_
## `eas branch:list`
@@ -276,7 +277,7 @@ DESCRIPTION
list all branches
```
_See code: [src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/branch/list.ts)_
_See code: [src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/branch/list.ts)_
## `eas branch:rename`
@@ -296,7 +297,7 @@ DESCRIPTION
rename a branch
```
_See code: [src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/branch/rename.ts)_
_See code: [src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/branch/rename.ts)_
## `eas branch:view [NAME]`
@@ -319,7 +320,7 @@ DESCRIPTION
view a branch
```
_See code: [src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/branch/view.ts)_
_See code: [src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/branch/view.ts)_
## `eas build`
@@ -349,7 +350,7 @@ DESCRIPTION
start a build
```
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/build/index.ts)_
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/build/index.ts)_
## `eas build:cancel [BUILD_ID]`
@@ -357,16 +358,18 @@ cancel a build
```
USAGE
$ eas build:cancel [BUILD_ID] [--non-interactive]
$ eas build:cancel [BUILD_ID] [--non-interactive] [-p android|ios|all] [-e <value>]
FLAGS
--non-interactive Run the command in non-interactive mode.
-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
cancel a build
```
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/build/cancel.ts)_
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/build/cancel.ts)_
## `eas build:configure`
@@ -383,7 +386,26 @@ DESCRIPTION
configure the project to support EAS Build
```
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/build/configure.ts)_
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v7.4.0/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.4.0/src/commands/build/delete.ts)_
## `eas build:inspect`
@@ -418,7 +440,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/v6.0.0/src/commands/build/inspect.ts)_
_See code: [src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/build/inspect.ts)_
## `eas build:list`
@@ -430,7 +452,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]
<value>] [--json --non-interactive] [--simulator]
FLAGS
--appBuildVersion=<value>
@@ -450,13 +472,16 @@ 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/v6.0.0/src/commands/build/list.ts)_
_See code: [src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/build/list.ts)_
## `eas build:resign`
@@ -482,7 +507,7 @@ DESCRIPTION
re-sign a build archive
```
_See code: [src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/build/resign.ts)_
_See code: [src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/build/resign.ts)_
## `eas build:run`
@@ -508,7 +533,7 @@ DESCRIPTION
run simulator/emulator builds from eas-cli
```
_See code: [src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/build/run.ts)_
_See code: [src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/build/run.ts)_
## `eas build:submit`
@@ -557,7 +582,7 @@ DESCRIPTION
get the latest version from EAS servers
```
_See code: [src/commands/build/version/get.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/build/version/get.ts)_
_See code: [src/commands/build/version/get.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/build/version/get.ts)_
## `eas build:version:set`
@@ -576,7 +601,7 @@ DESCRIPTION
update version of an app
```
_See code: [src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/build/version/set.ts)_
_See code: [src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/build/version/set.ts)_
## `eas build:version:sync`
@@ -595,7 +620,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/v6.0.0/src/commands/build/version/sync.ts)_
_See code: [src/commands/build/version/sync.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/build/version/sync.ts)_
## `eas build:view [BUILD_ID]`
@@ -612,7 +637,7 @@ DESCRIPTION
view a build for your project
```
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/build/view.ts)_
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/build/view.ts)_
## `eas channel:create [NAME]`
@@ -633,7 +658,7 @@ DESCRIPTION
create a channel
```
_See code: [src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/channel/create.ts)_
_See code: [src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/channel/create.ts)_
## `eas channel:edit [NAME]`
@@ -655,7 +680,7 @@ DESCRIPTION
point a channel at a new branch
```
_See code: [src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/channel/edit.ts)_
_See code: [src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/channel/edit.ts)_
## `eas channel:list`
@@ -675,7 +700,7 @@ DESCRIPTION
list all channels
```
_See code: [src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/channel/list.ts)_
_See code: [src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/channel/list.ts)_
## `eas channel:rollout [CHANNEL]`
@@ -707,7 +732,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/v6.0.0/src/commands/channel/rollout.ts)_
_See code: [src/commands/channel/rollout.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/channel/rollout.ts)_
## `eas channel:view [NAME]`
@@ -730,7 +755,7 @@ DESCRIPTION
view a channel
```
_See code: [src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/channel/view.ts)_
_See code: [src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/channel/view.ts)_
## `eas config`
@@ -751,7 +776,7 @@ DESCRIPTION
display project configuration (app.json + eas.json)
```
_See code: [src/commands/config.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/config.ts)_
_See code: [src/commands/config.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/config.ts)_
## `eas credentials`
@@ -768,7 +793,7 @@ DESCRIPTION
manage credentials
```
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/credentials.ts)_
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/credentials.ts)_
## `eas device:create`
@@ -782,7 +807,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/v6.0.0/src/commands/device/create.ts)_
_See code: [src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/device/create.ts)_
## `eas device:delete`
@@ -802,7 +827,7 @@ DESCRIPTION
remove a registered device from your account
```
_See code: [src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/device/delete.ts)_
_See code: [src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/device/delete.ts)_
## `eas device:list`
@@ -823,7 +848,7 @@ DESCRIPTION
list all registered devices for your account
```
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/device/list.ts)_
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/device/list.ts)_
## `eas device:rename`
@@ -844,7 +869,7 @@ DESCRIPTION
rename a registered device
```
_See code: [src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/device/rename.ts)_
_See code: [src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/device/rename.ts)_
## `eas device:view [UDID]`
@@ -858,7 +883,7 @@ DESCRIPTION
view a device for your project
```
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/device/view.ts)_
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/device/view.ts)_
## `eas diagnostics`
@@ -872,7 +897,7 @@ DESCRIPTION
display environment info
```
_See code: [src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/diagnostics.ts)_
_See code: [src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/diagnostics.ts)_
## `eas help [COMMAND]`
@@ -960,7 +985,7 @@ DESCRIPTION
validate the local store configuration
```
_See code: [src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/metadata/lint.ts)_
_See code: [src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/metadata/lint.ts)_
## `eas metadata:pull`
@@ -977,7 +1002,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/v6.0.0/src/commands/metadata/pull.ts)_
_See code: [src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/metadata/pull.ts)_
## `eas metadata:push`
@@ -994,7 +1019,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/v6.0.0/src/commands/metadata/push.ts)_
_See code: [src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/metadata/push.ts)_
## `eas open`
@@ -1008,7 +1033,7 @@ DESCRIPTION
open the project page in a web browser
```
_See code: [src/commands/open.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/open.ts)_
_See code: [src/commands/open.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/open.ts)_
## `eas project:info`
@@ -1022,7 +1047,7 @@ DESCRIPTION
information about the current project
```
_See code: [src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/project/info.ts)_
_See code: [src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/project/info.ts)_
## `eas project:init`
@@ -1044,7 +1069,7 @@ ALIASES
$ eas init
```
_See code: [src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/project/init.ts)_
_See code: [src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/project/init.ts)_
## `eas secret:create`
@@ -1067,7 +1092,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/v6.0.0/src/commands/secret/create.ts)_
_See code: [src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/secret/create.ts)_
## `eas secret:delete`
@@ -1085,7 +1110,7 @@ DESCRIPTION
delete an environment secret by ID
```
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/secret/delete.ts)_
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/secret/delete.ts)_
## `eas secret:list`
@@ -1099,7 +1124,7 @@ DESCRIPTION
list environment secrets available for your current app
```
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/secret/list.ts)_
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/secret/list.ts)_
## `eas secret:push`
@@ -1119,7 +1144,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/v6.0.0/src/commands/secret/push.ts)_
_See code: [src/commands/secret/push.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/secret/push.ts)_
## `eas submit`
@@ -1149,7 +1174,7 @@ ALIASES
$ eas build:submit
```
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/submit.ts)_
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/submit.ts)_
## `eas update`
@@ -1158,8 +1183,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] [--dev] [--auto] [--private-key-path
<value>] [--json --non-interactive]
--skip-bundler] [--group <value> | | ] [--clear-cache] [-p android|ios|all] [--auto] [--private-key-path <value>]
[--json --non-interactive]
FLAGS
-m, --message=<value> A short message describing the update
@@ -1168,7 +1193,6 @@ 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.
@@ -1183,7 +1207,7 @@ DESCRIPTION
publish an update group
```
_See code: [src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/update/index.ts)_
_See code: [src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/update/index.ts)_
## `eas update:configure`
@@ -1201,7 +1225,7 @@ DESCRIPTION
configure the project to support EAS Update
```
_See code: [src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/update/configure.ts)_
_See code: [src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/update/configure.ts)_
## `eas update:delete GROUPID`
@@ -1222,7 +1246,7 @@ DESCRIPTION
delete all the updates in an update group
```
_See code: [src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/update/delete.ts)_
_See code: [src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/update/delete.ts)_
## `eas update:list`
@@ -1244,7 +1268,7 @@ DESCRIPTION
view the recent updates
```
_See code: [src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/update/list.ts)_
_See code: [src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/update/list.ts)_
## `eas update:republish`
@@ -1271,7 +1295,7 @@ DESCRIPTION
roll back to an existing update
```
_See code: [src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/update/republish.ts)_
_See code: [src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/update/republish.ts)_
## `eas update:roll-back-to-embedded`
@@ -1298,7 +1322,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/v6.0.0/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/v7.4.0/src/commands/update/roll-back-to-embedded.ts)_
## `eas update:rollback`
@@ -1317,7 +1341,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/v6.0.0/src/commands/update/rollback.ts)_
_See code: [src/commands/update/rollback.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/update/rollback.ts)_
## `eas update:view GROUPID`
@@ -1337,7 +1361,7 @@ DESCRIPTION
update group details
```
_See code: [src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/update/view.ts)_
_See code: [src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/update/view.ts)_
## `eas webhook:create`
@@ -1358,7 +1382,7 @@ DESCRIPTION
create a webhook
```
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/webhook/create.ts)_
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/webhook/create.ts)_
## `eas webhook:delete [ID]`
@@ -1378,7 +1402,7 @@ DESCRIPTION
delete a webhook
```
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/webhook/delete.ts)_
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/webhook/delete.ts)_
## `eas webhook:list`
@@ -1396,7 +1420,7 @@ DESCRIPTION
list webhooks
```
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/webhook/list.ts)_
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/webhook/list.ts)_
## `eas webhook:update`
@@ -1418,7 +1442,7 @@ DESCRIPTION
update a webhook
```
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/webhook/update.ts)_
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/webhook/update.ts)_
## `eas webhook:view ID`
@@ -1435,7 +1459,7 @@ DESCRIPTION
view a webhook
```
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v6.0.0/src/commands/webhook/view.ts)_
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v7.4.0/src/commands/webhook/view.ts)_
## `eas whoami`
+260
View File
@@ -4726,6 +4726,18 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "googleServiceAccountKeyForFcmV1",
"description": null,
"args": [],
"type": {
"kind": "OBJECT",
"name": "GoogleServiceAccountKey",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "googleServiceAccountKeyForSubmissions",
"description": null,
@@ -4829,6 +4841,18 @@
"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,
@@ -4916,6 +4940,71 @@
"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",
@@ -4998,6 +5087,55 @@
"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",
@@ -14573,6 +14711,22 @@
"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,
@@ -15872,6 +16026,18 @@
"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,
@@ -15970,6 +16136,18 @@
"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,
@@ -16894,6 +17072,18 @@
"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,
@@ -17959,6 +18149,22 @@
"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,
@@ -19330,6 +19536,18 @@
"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/*`.",
@@ -23242,6 +23460,18 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "submitProfile",
"description": null,
"args": [],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "targetPattern",
"description": null,
@@ -27500,6 +27730,12 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "DID_SUBSCRIBE_TO_EAS_AT_LEAST_ONCE",
"description": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "EAS_MASTER_LIST",
"description": null,
@@ -28447,6 +28683,12 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "BUILD_ERRORED",
"description": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "BUILD_LIMIT_THRESHOLD_EXCEEDED",
"description": null,
@@ -28465,6 +28707,12 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "SUBMISSION_ERRORED",
"description": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "TEST",
"description": null,
@@ -37050,6 +37298,18 @@
"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": "6.0.0",
"version": "7.4.0",
"author": "Expo <[email protected]>",
"bin": {
"eas": "./bin/run"
},
"bugs": "https://github.com/expo/eas-cli/issues",
"dependencies": {
"@expo/apple-utils": "1.3.2",
"@expo/apple-utils": "1.5.0",
"@expo/code-signing-certificates": "0.0.5",
"@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/config": "8.5.4",
"@expo/config-plugins": "7.8.4",
"@expo/config-types": "50.0.0",
"@expo/eas-build-job": "1.0.78",
"@expo/eas-json": "7.4.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.2.5",
"@expo/prebuild-config": "6.7.3",
"@expo/results": "1.0.0",
"@expo/rudder-sdk-node": "1.1.1",
"@expo/spawn-async": "1.7.0",
"@expo/steps": "1.0.51",
"@expo/steps": "1.0.81",
"@expo/timeago.js": "1.0.0",
"@oclif/core": "^1.26.2",
"@oclif/plugin-autocomplete": "^2.3.10",
@@ -92,5 +92,6 @@ function createMockBuildFragment({
},
status: BuildStatus.InQueue,
resourceClass: BuildResourceClass.AndroidMedium,
isForIosSimulator: false,
};
}
@@ -92,5 +92,6 @@ function createMockBuildFragment({
},
status: BuildStatus.InQueue,
resourceClass: BuildResourceClass.AndroidMedium,
isForIosSimulator: false,
};
}
+1 -2
View File
@@ -99,14 +99,13 @@ export async function prepareAndroidBuildAsync(
return await ensureAndroidCredentialsAsync(ctx);
},
syncProjectConfigurationAsync: async () => {
await syncProjectConfigurationAsync(ctx.graphqlClient, {
await syncProjectConfigurationAsync({
projectDir: ctx.projectDir,
exp: ctx.exp,
localAutoIncrement:
ctx.easJsonCliConfig?.appVersionSource === AppVersionSource.REMOTE
? false
: ctx.buildProfile.autoIncrement,
projectId: ctx.projectId,
vcsClient: ctx.vcsClient,
});
},
@@ -7,36 +7,30 @@ 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(
graphqlClient: ExpoGraphqlClient,
{
projectDir,
exp,
localAutoIncrement,
projectId,
vcsClient,
}: {
projectDir: string;
exp: ExpoConfig;
localAutoIncrement?: AndroidVersionAutoIncrement;
projectId: string;
vcsClient: Client;
}
): Promise<void> {
export async function syncProjectConfigurationAsync({
projectDir,
exp,
localAutoIncrement,
vcsClient,
}: {
projectDir: string;
exp: ExpoConfig;
localAutoIncrement?: AndroidVersionAutoIncrement;
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(graphqlClient, projectDir, exp, projectId);
await syncUpdatesConfigurationAsync(projectDir, exp);
}
await bumpVersionAsync({ projectDir, exp, bumpStrategy: versionBumpStrategy });
} else {
@@ -232,7 +232,9 @@ export async function resolveRemoteVersionCodeAsync(
applicationIdentifier: applicationId,
storeVersion: localVersions.appVersion ?? exp.version ?? '1.0.0',
buildVersion: currentBuildVersion,
runtimeVersion: Updates.getRuntimeVersionNullable(exp, Platform.ANDROID) ?? undefined,
runtimeVersion:
(await Updates.getRuntimeVersionNullableAsync(projectDir, exp, Platform.ANDROID)) ??
undefined,
});
spinner.succeed(`Initialized versionCode with ${chalk.bold(currentBuildVersion)}.`);
} catch (err) {
@@ -254,7 +256,9 @@ export async function resolveRemoteVersionCodeAsync(
applicationIdentifier: applicationId,
storeVersion: localVersions.appVersion ?? exp.version ?? '1.0.0',
buildVersion: String(nextBuildVersion),
runtimeVersion: Updates.getRuntimeVersionNullable(exp, Platform.ANDROID) ?? undefined,
runtimeVersion:
(await Updates.getRuntimeVersionNullableAsync(projectDir, exp, Platform.ANDROID)) ??
undefined,
});
spinner.succeed(
`Incremented versionCode from ${chalk.bold(currentBuildVersion)} to ${chalk.bold(
+1 -2
View File
@@ -80,7 +80,7 @@ export async function prepareIosBuildAsync(
return ensureIosCredentialsAsync(ctx, ctx.ios.targets);
},
syncProjectConfigurationAsync: async () => {
await syncProjectConfigurationAsync(ctx.graphqlClient, {
await syncProjectConfigurationAsync({
projectDir: ctx.projectDir,
exp: ctx.exp,
targets: ctx.ios.targets,
@@ -88,7 +88,6 @@ export async function prepareIosBuildAsync(
ctx.easJsonCliConfig?.appVersionSource === AppVersionSource.REMOTE
? false
: ctx.buildProfile.autoIncrement,
projectId: ctx.projectId,
vcsClient: ctx.vcsClient,
});
},
@@ -3,37 +3,31 @@ 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(
graphqlClient: ExpoGraphqlClient,
{
projectDir,
exp,
targets,
localAutoIncrement,
projectId,
vcsClient,
}: {
projectDir: string;
exp: ExpoConfig;
targets: Target[];
localAutoIncrement?: IosVersionAutoIncrement;
projectId: string;
vcsClient: Client;
}
): Promise<void> {
export async function syncProjectConfigurationAsync({
projectDir,
exp,
targets,
localAutoIncrement,
vcsClient,
}: {
projectDir: string;
exp: ExpoConfig;
targets: Target[];
localAutoIncrement?: IosVersionAutoIncrement;
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(graphqlClient, vcsClient, projectDir, exp, projectId);
await syncUpdatesConfigurationAsync(vcsClient, projectDir, exp);
}
await bumpVersionAsync({ projectDir, exp, bumpStrategy: versionBumpStrategy, targets });
} else {
+6 -2
View File
@@ -342,7 +342,9 @@ export async function resolveRemoteBuildNumberAsync(
applicationIdentifier: applicationTarget.bundleIdentifier,
storeVersion: localShortVersion ?? '1.0.0',
buildVersion: currentBuildVersion,
runtimeVersion: Updates.getRuntimeVersionNullable(exp, Platform.IOS) ?? undefined,
runtimeVersion:
(await Updates.getRuntimeVersionNullableAsync(projectDir, exp, Platform.IOS)) ??
undefined,
});
spinner.succeed(`Initialized buildNumber with ${chalk.bold(currentBuildVersion)}.`);
} catch (err) {
@@ -364,7 +366,9 @@ export async function resolveRemoteBuildNumberAsync(
applicationIdentifier: applicationTarget.bundleIdentifier,
storeVersion: localShortVersion ?? '1.0.0',
buildVersion: nextBuildVersion,
runtimeVersion: Updates.getRuntimeVersionNullable(exp, Platform.IOS) ?? undefined,
runtimeVersion:
(await Updates.getRuntimeVersionNullableAsync(projectDir, 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.56';
const PLUGIN_PACKAGE_VERSION = '1.0.71';
export enum LocalBuildMode {
/**
+19 -10
View File
@@ -1,4 +1,3 @@
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';
@@ -8,8 +7,14 @@ 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, isExpoUpdatesInstalled } from '../project/projectUtils';
import {
getUsername,
isClassicUpdatesSupportedAsync,
isExpoUpdatesInstalled,
} from '../project/projectUtils';
import { resolveRuntimeVersionAsync } from '../project/resolveRuntimeVersionAsync';
import {
readChannelSafelyAsync as readAndroidChannelSafelyAsync,
readReleaseChannelSafelyAsync as readAndroidReleaseChannelSafelyAsync,
@@ -24,10 +29,7 @@ export async function collectMetadataAsync<T extends Platform>(
ctx: BuildContext<T>
): Promise<Metadata> {
const channelOrReleaseChannel = await resolveChannelOrReleaseChannelAsync(ctx);
const distribution =
('simulator' in ctx.buildProfile && ctx.buildProfile.simulator
? 'simulator'
: ctx.buildProfile.distribution) ?? 'store';
const distribution = ctx.buildProfile.distribution ?? BuildDistributionType.STORE;
const metadata: Metadata = {
trackingContext: ctx.analyticsEventProperties,
...(await maybeResolveVersionsAsync(ctx)),
@@ -35,7 +37,7 @@ export async function collectMetadataAsync<T extends Platform>(
workflow: ctx.workflow,
credentialsSource: ctx.buildProfile.credentialsSource,
sdkVersion: ctx.exp.sdkVersion,
runtimeVersion: Updates.getRuntimeVersionNullable(ctx.exp, ctx.platform) ?? undefined,
runtimeVersion: (await resolveRuntimeVersionAsync(ctx)) ?? undefined,
reactNativeVersion: await getReactNativeVersionAsync(ctx.projectDir),
...channelOrReleaseChannel,
distribution,
@@ -64,6 +66,7 @@ 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);
}
@@ -123,13 +126,19 @@ 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 };
}
@@ -334,7 +334,6 @@ async function prepareAndStartBuildAsync({
);
if (buildProfile.profile.channel) {
await validateExpoUpdatesInstalledAsProjectDependencyAsync({
graphqlClient,
exp: buildCtx.exp,
projectId: buildCtx.projectId,
projectDir,
@@ -479,7 +478,6 @@ async function maybeDownloadAndRunSimulatorBuildsAsync(
async function validateExpoUpdatesInstalledAsProjectDependencyAsync({
exp,
graphqlClient,
projectId,
projectDir,
vcsClient,
@@ -487,7 +485,6 @@ async function validateExpoUpdatesInstalledAsProjectDependencyAsync({
nonInteractive,
sdkVersion,
}: {
graphqlClient: ExpoGraphqlClient;
exp: ExpoConfig;
projectId: string;
projectDir: string;
@@ -516,7 +513,7 @@ async function validateExpoUpdatesInstalledAsProjectDependencyAsync({
message: `Would you like to install the "expo-updates" package and configure EAS Update now?`,
});
if (installExpoUpdates) {
await ensureEASUpdateIsConfiguredAsync(graphqlClient, {
await ensureEASUpdateIsConfiguredAsync({
exp,
projectId,
projectDir,
+1
View File
@@ -11,5 +11,6 @@ export enum BuildStatus {
export enum BuildDistributionType {
STORE = 'store',
INTERNAL = 'internal',
/** @deprecated Use simulator flag instead */
SIMULATOR = 'simulator',
}
@@ -11,10 +11,7 @@ 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,
ensureUseClassicUpdatesIsRemovedAsync,
} from '../../update/configure';
import { ensureEASUpdateIsConfiguredInEasJsonAsync } from '../../update/configure';
import { syncUpdatesConfigurationAsync as syncIosUpdatesConfigurationAsync } from '../../update/ios/UpdatesModule';
export default class BuildConfigure extends EasCommand {
@@ -38,7 +35,6 @@ 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,
@@ -70,12 +66,6 @@ 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);
}
@@ -84,20 +74,14 @@ 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(graphqlClient, projectDir, exp, projectId);
await syncAndroidUpdatesConfigurationAsync(projectDir, exp);
}
}
if ([RequestedPlatform.Ios, RequestedPlatform.All].includes(platform)) {
const workflow = await resolveWorkflowAsync(projectDir, Platform.IOS, vcsClient);
if (workflow === Workflow.GENERIC) {
await syncIosUpdatesConfigurationAsync(
graphqlClient,
vcsClient,
projectDir,
exp,
projectId
);
await syncIosUpdatesConfigurationAsync(vcsClient, projectDir, exp);
}
}
}
@@ -10,6 +10,7 @@ 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';
@@ -51,6 +52,10 @@ 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 = {
@@ -69,6 +74,17 @@ 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 },
@@ -100,6 +116,7 @@ export default class BuildList extends EasCommand {
appIdentifier: flags.appIdentifier,
buildProfile: flags.buildProfile,
gitCommitHash: flags.gitCommitHash,
simulator: flags.simulator,
},
paginatedQueryOptions,
});
+4 -5
View File
@@ -11,7 +11,7 @@ import {
PaginatedQueryOptions,
getPaginatedQueryOptions,
} from '../../commandUtils/pagination';
import { AppPlatform, BuildFragment, BuildStatus, DistributionType } from '../../graphql/generated';
import { AppPlatform, BuildFragment, BuildStatus } from '../../graphql/generated';
import { BuildQuery } from '../../graphql/queries/BuildQuery';
import Log from '../../log';
import { appPlatformDisplayNames } from '../../platform';
@@ -200,8 +200,7 @@ async function maybeGetBuildAsync(
projectId: string,
paginatedQueryOptions: PaginatedQueryOptions
): Promise<BuildFragment | null> {
const distributionType =
flags.selectedPlatform === AppPlatform.Ios ? DistributionType.Simulator : undefined;
const simulator = flags.selectedPlatform === AppPlatform.Ios ? true : undefined;
if (flags.runArchiveFlags.id) {
const build = await BuildQuery.byIdAsync(graphqlClient, flags.runArchiveFlags.id);
@@ -219,9 +218,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),
@@ -235,9 +234,9 @@ async function maybeGetBuildAsync(
projectId,
filter: {
platform: flags.selectedPlatform,
distribution: distributionType,
status: BuildStatus.Finished,
buildProfile: flags.profile,
simulator,
},
});
@@ -1,4 +1,4 @@
import { getRuntimeVersionNullable } from '@expo/config-plugins/build/utils/Updates';
import { getRuntimeVersionNullableAsync } 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,7 +116,8 @@ export default class BuildVersionSetView extends EasCommand {
applicationIdentifier,
storeVersion: exp.version ?? '1.0.0',
buildVersion: String(version),
runtimeVersion: getRuntimeVersionNullable(exp, platform) ?? undefined,
runtimeVersion:
(await getRuntimeVersionNullableAsync(projectDir, exp, platform)) ?? undefined,
});
}
}
@@ -4,7 +4,11 @@ import { print } from 'graphql';
import gql from 'graphql-tag';
import { selectBranchOnAppAsync } from '../../branch/queries';
import { hasEmptyBranchMap, hasStandardBranchMap } from '../../channel/branch-mapping';
import {
getAlwaysTrueBranchMapping,
hasEmptyBranchMap,
hasStandardBranchMap,
} from '../../channel/branch-mapping';
import { selectChannelOnAppAsync } from '../../channel/queries';
import EasCommand from '../../commandUtils/EasCommand';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
@@ -124,11 +128,7 @@ export default class ChannelEdit extends EasCommand {
const channel = await updateChannelBranchMappingAsync(graphqlClient, {
channelId: existingChannel.id,
// todo: move branch mapping logic to utility
branchMapping: JSON.stringify({
data: [{ branchId: branch.id, branchMappingLogic: 'true' }],
version: 0,
}),
branchMapping: JSON.stringify(getAlwaysTrueBranchMapping(branch.id)),
});
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 },
privateProjectConfig: { exp, projectId, projectDir },
loggedIn: { graphqlClient },
} = await this.getContextAsync(ChannelRollout, {
nonInteractive: argsAndFlags.nonInteractive,
@@ -141,9 +141,8 @@ export default class ChannelRollout extends EasCommand {
enableJsonOutput();
}
const app = { projectId, exp };
const app = { projectId, exp, projectDir };
const ctx = {
projectId,
nonInteractive: argsAndFlags.nonInteractive,
graphqlClient,
app,
+14 -2
View File
@@ -1,4 +1,4 @@
import { getProjectConfigDescription } from '@expo/config';
import { ConfigError, getProjectConfigDescription } from '@expo/config';
import { ExpoConfig } from '@expo/config-types';
import { Flags } from '@oclif/core';
import chalk from 'chalk';
@@ -60,7 +60,19 @@ export default class ProjectInit extends EasCommand {
projectDir: string,
modifications: Partial<ExpoConfig>
): Promise<void> {
const result = await createOrModifyExpoConfigAsync(projectDir, modifications);
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;
}
}
switch (result.type) {
case 'success':
break;
@@ -1,30 +0,0 @@
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.`
);
});
});
@@ -324,7 +324,7 @@ function mockTestExport({
uniqueUploadedAssetPaths: [],
});
jest.mocked(Updates.getRuntimeVersion).mockReturnValue(runtimeVersion);
jest.mocked(Updates.getRuntimeVersionAsync).mockResolvedValue(runtimeVersion);
return { inputDir: exportDir, platforms, runtimeVersion };
}
@@ -84,7 +84,7 @@ describe(UpdateRollBackToEmbedded.name, () => {
mockTestProject();
const platforms = ['android', 'ios'];
const runtimeVersion = 'exposdk:47.0.0';
jest.mocked(Updates.getRuntimeVersion).mockReturnValue(runtimeVersion);
jest.mocked(Updates.getRuntimeVersionAsync).mockResolvedValue(runtimeVersion);
jest.mocked(ensureBranchExistsAsync).mockResolvedValue({
branchId: 'branch123',
@@ -106,7 +106,7 @@ describe(UpdateRollBackToEmbedded.name, () => {
const { projectId } = mockTestProject();
const platforms = ['android', 'ios'];
const runtimeVersion = 'exposdk:47.0.0';
jest.mocked(Updates.getRuntimeVersion).mockReturnValue(runtimeVersion);
jest.mocked(Updates.getRuntimeVersionAsync).mockResolvedValue(runtimeVersion);
jest.mocked(getBranchNameFromChannelNameAsync).mockResolvedValue('branchFromChannel');
jest.mocked(ensureBranchExistsAsync).mockResolvedValue({
@@ -154,7 +154,7 @@ describe(UpdateRollBackToEmbedded.name, () => {
const platforms = ['ios'];
const runtimeVersion = 'exposdk:47.0.0';
jest.mocked(Updates.getRuntimeVersion).mockReturnValue(runtimeVersion);
jest.mocked(Updates.getRuntimeVersionAsync).mockResolvedValue(runtimeVersion);
// Mock an existing branch, so we don't create a new one
jest.mocked(ensureBranchExistsAsync).mockResolvedValue({
@@ -35,7 +35,6 @@ 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'],
@@ -47,7 +46,7 @@ export default class UpdateConfigure extends EasCommand {
await vcsClient.ensureRepoExistsAsync();
await ensureEASUpdateIsConfiguredAsync(graphqlClient, {
await ensureEASUpdateIsConfiguredAsync({
exp,
projectId,
projectDir,
+11 -19
View File
@@ -4,6 +4,7 @@ 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';
@@ -29,7 +30,6 @@ import {
collectAssetsAsync,
defaultPublishPlatforms,
filterExportedPlatformsByFlag,
generateEasMetadataAsync,
getBranchNameForCommandAsync,
getRequestedPlatform,
getRuntimeToPlatformMappingFromRuntimeVersions,
@@ -56,7 +56,6 @@ import { maybeWarnAboutEasOutagesAsync } from '../../utils/statuspageService';
type RawUpdateFlags = {
auto: boolean;
dev: boolean;
branch?: string;
channel?: string;
message?: string;
@@ -75,7 +74,6 @@ type RawUpdateFlags = {
type UpdateFlags = {
auto: boolean;
dev: boolean;
platform: ExpoCLIExportPlatformFlag;
branchName?: string;
channelName?: string;
@@ -136,10 +134,6 @@ 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',
@@ -165,7 +159,6 @@ export default class UpdatePublish extends EasCommand {
auto: autoFlag,
platform: platformFlag,
channelName: channelNameArg,
dev,
updateMessage: updateMessageArg,
inputDir,
skipBundler,
@@ -189,6 +182,9 @@ export default class UpdatePublish extends EasCommand {
enableJsonOutput();
}
await vcsClient.ensureRepoExistsAsync();
await ensureRepoIsCleanAsync(vcsClient, nonInteractive);
const {
exp: expPossiblyWithoutEasUpdateConfigured,
projectId,
@@ -197,7 +193,7 @@ export default class UpdatePublish extends EasCommand {
await maybeWarnAboutEasOutagesAsync(graphqlClient, [StatuspageServiceName.EasUpdate]);
await ensureEASUpdateIsConfiguredAsync(graphqlClient, {
await ensureEASUpdateIsConfiguredAsync({
exp: expPossiblyWithoutEasUpdateConfigured,
platform: getRequestedPlatform(platformFlag),
projectDir,
@@ -231,7 +227,7 @@ export default class UpdatePublish extends EasCommand {
if (!skipBundler) {
const bundleSpinner = ora().start('Exporting...');
try {
await buildBundlesAsync({ projectDir, inputDir, dev, exp, platformFlag, clearCache });
await buildBundlesAsync({ projectDir, inputDir, exp, platformFlag, clearCache });
bundleSpinner.succeed('Exported bundle(s)');
} catch (e) {
bundleSpinner.fail('Export failed');
@@ -363,12 +359,12 @@ export default class UpdatePublish extends EasCommand {
throw e;
}
const runtimeVersions = await getRuntimeVersionObjectAsync(
const runtimeVersions = await getRuntimeVersionObjectAsync({
exp,
realizedPlatforms,
platforms: realizedPlatforms,
projectDir,
vcsClient
);
vcsClient,
});
const runtimeToPlatformMapping =
getRuntimeToPlatformMappingFromRuntimeVersions(runtimeVersions);
@@ -469,9 +465,6 @@ export default class UpdatePublish extends EasCommand {
throw e;
}
if (!skipBundler) {
await generateEasMetadataAsync(distRoot, getUpdateJsonInfosForUpdates(newUpdates));
}
if (jsonFlag) {
printJsonOnlyOutput(getUpdateJsonInfosForUpdates(newUpdates));
} else {
@@ -547,7 +540,7 @@ export default class UpdatePublish extends EasCommand {
private sanitizeFlags(flags: RawUpdateFlags): UpdateFlags {
const nonInteractive = flags['non-interactive'] ?? false;
const { auto, branch: branchName, channel: channelName, dev, message: updateMessage } = flags;
const { auto, branch: branchName, channel: channelName, 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',
@@ -576,7 +569,6 @@ export default class UpdatePublish extends EasCommand {
auto,
branchName,
channelName,
dev,
updateMessage,
inputDir: flags['input-dir'],
skipBundler: flags['skip-bundler'],
@@ -293,12 +293,7 @@ async function askUpdatesFromChannelNameAsync(
nonInteractive,
}: { projectId: string; channelName: string; json: boolean; nonInteractive: boolean }
): Promise<UpdateToRepublish[]> {
const branchName = await getBranchNameFromChannelNameAsync(
graphqlClient,
projectId,
channelName,
{ json, nonInteractive, offset: 0 }
);
const branchName = await getBranchNameFromChannelNameAsync(graphqlClient, projectId, channelName);
return await askUpdatesFromBranchNameAsync(graphqlClient, {
projectId,
@@ -148,7 +148,7 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
await maybeWarnAboutEasOutagesAsync(graphqlClient, [StatuspageServiceName.EasUpdate]);
await ensureEASUpdateIsConfiguredAsync(graphqlClient, {
await ensureEASUpdateIsConfiguredAsync({
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,
realizedPlatforms,
platforms: realizedPlatforms,
projectDir,
vcsClient
);
vcsClient,
});
let newUpdates: UpdatePublishMutation['updateBranch']['publishUpdateGroups'];
const publishSpinner = ora('Publishing...').start();
@@ -0,0 +1,33 @@
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;
}
}
@@ -6,7 +6,7 @@ import Log from '../../../log';
import { CredentialsContext } from '../../context';
import { AppLookupParams } from '../api/GraphqlClient';
export class AssignGoogleServiceAccountKey {
export class AssignGoogleServiceAccountKeyForSubmissions {
constructor(private app: AppLookupParams) {}
public async runAsync(
@@ -46,7 +46,7 @@ export class CreateGoogleServiceAccountKey {
Log.log(
`${chalk.bold(
'A Google Service Account JSON key is required to upload your app to Google Play Store'
'A Google Service Account JSON key is required for uploading your app to Google Play Store, and for sending Android Notifications via FCM V1.'
)}.\n` +
`If you're not sure what this is or how to create one, ${learnMore(
'https://expo.fyi/creating-google-service-account',
@@ -0,0 +1,87 @@
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))
);
}
}
@@ -1,6 +1,6 @@
import nullthrows from 'nullthrows';
import { AssignGoogleServiceAccountKey } from './AssignGoogleServiceAccountKey';
import { AssignGoogleServiceAccountKeyForSubmissions } from './AssignGoogleServiceAccountKeyForSubmissions';
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 SetUpGoogleServiceAccountKey {
export class SetUpGoogleServiceAccountKeyForSubmissions {
constructor(private app: AppLookupParams) {}
public async runAsync(ctx: CredentialsContext): Promise<CommonAndroidAppCredentialsFragment> {
@@ -46,7 +46,10 @@ export class SetUpGoogleServiceAccountKey {
} else {
googleServiceAccountKey = await this.createOrUseExistingKeyAsync(ctx);
}
return await new AssignGoogleServiceAccountKey(this.app).runAsync(ctx, googleServiceAccountKey);
return await new AssignGoogleServiceAccountKeyForSubmissions(this.app).runAsync(
ctx,
googleServiceAccountKey
);
}
private async isGoogleServiceAccountKeySetupAsync(ctx: CredentialsContext): Promise<boolean> {
@@ -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 { AssignGoogleServiceAccountKey } from '../AssignGoogleServiceAccountKey';
import { AssignGoogleServiceAccountKeyForSubmissions } from '../AssignGoogleServiceAccountKeyForSubmissions';
import { getAppLookupParamsFromContextAsync } from '../BuildCredentialsUtils';
jest.mock('../../../../graphql/queries/AppQuery');
describe(AssignGoogleServiceAccountKey, () => {
describe(AssignGoogleServiceAccountKeyForSubmissions, () => {
beforeEach(() => {
jest.mocked(AppQuery.byIdAsync).mockResolvedValue(testAppQueryByIdResponse);
});
@@ -16,7 +16,9 @@ describe(AssignGoogleServiceAccountKey, () => {
nonInteractive: false,
});
const appLookupParams = await getAppLookupParamsFromContextAsync(ctx);
const assignGoogleServiceAccountKeyAction = new AssignGoogleServiceAccountKey(appLookupParams);
const assignGoogleServiceAccountKeyAction = new AssignGoogleServiceAccountKeyForSubmissions(
appLookupParams
);
await assignGoogleServiceAccountKeyAction.runAsync(ctx, testGoogleServiceAccountKeyFragment);
// expect app credentials to be fetched/created, then updated
@@ -30,7 +32,9 @@ describe(AssignGoogleServiceAccountKey, () => {
nonInteractive: true,
});
const appLookupParams = await getAppLookupParamsFromContextAsync(ctx);
const assignGoogleServiceAccountKeyAction = new AssignGoogleServiceAccountKey(appLookupParams);
const assignGoogleServiceAccountKeyAction = new AssignGoogleServiceAccountKeyForSubmissions(
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 { SetUpGoogleServiceAccountKey } from '../SetUpGoogleServiceAccountKey';
import { SetUpGoogleServiceAccountKeyForSubmissions } from '../SetUpGoogleServiceAccountKeyForSubmissions';
jest.mock('../../../../prompts');
jest.mock('fs');
@@ -24,7 +24,7 @@ beforeEach(() => {
vol.reset();
});
describe(SetUpGoogleServiceAccountKey, () => {
describe(SetUpGoogleServiceAccountKeyForSubmissions, () => {
beforeEach(() => {
jest.mocked(AppQuery.byIdAsync).mockResolvedValue(testAppQueryByIdResponse);
});
@@ -39,7 +39,9 @@ describe(SetUpGoogleServiceAccountKey, () => {
},
});
const appLookupParams = await getAppLookupParamsFromContextAsync(ctx);
const setupGoogleServiceAccountKeyAction = new SetUpGoogleServiceAccountKey(appLookupParams);
const setupGoogleServiceAccountKeyAction = new SetUpGoogleServiceAccountKeyForSubmissions(
appLookupParams
);
await setupGoogleServiceAccountKeyAction.runAsync(ctx);
expect(ctx.android.createGoogleServiceAccountKeyAsync).not.toHaveBeenCalled();
@@ -62,7 +64,9 @@ describe(SetUpGoogleServiceAccountKey, () => {
},
});
const appLookupParams = await getAppLookupParamsFromContextAsync(ctx);
const setupGoogleServiceAccountKeyAction = new SetUpGoogleServiceAccountKey(appLookupParams);
const setupGoogleServiceAccountKeyAction = new SetUpGoogleServiceAccountKeyForSubmissions(
appLookupParams
);
await setupGoogleServiceAccountKeyAction.runAsync(ctx);
expect(ctx.android.createGoogleServiceAccountKeyAsync).toHaveBeenCalledTimes(1);
@@ -73,7 +77,9 @@ describe(SetUpGoogleServiceAccountKey, () => {
nonInteractive: true,
});
const appLookupParams = await getAppLookupParamsFromContextAsync(ctx);
const setupGoogleServiceAccountKeyAction = new SetUpGoogleServiceAccountKey(appLookupParams);
const setupGoogleServiceAccountKeyAction = new SetUpGoogleServiceAccountKeyForSubmissions(
appLookupParams
);
await expect(setupGoogleServiceAccountKeyAction.runAsync(ctx)).rejects.toThrowError(
MissingCredentialsNonInteractiveError
);
@@ -106,9 +106,11 @@ export async function updateAndroidAppCredentialsAsync(
{
androidFcmId,
googleServiceAccountKeyForSubmissionsId,
googleServiceAccountKeyForFcmV1Id,
}: {
androidFcmId?: string;
googleServiceAccountKeyForSubmissionsId?: string;
googleServiceAccountKeyForFcmV1Id?: string;
}
): Promise<CommonAndroidAppCredentialsFragment> {
let updatedAppCredentials = appCredentials;
@@ -127,6 +129,14 @@ export async function updateAndroidAppCredentialsAsync(
googleServiceAccountKeyForSubmissionsId
);
}
if (googleServiceAccountKeyForFcmV1Id) {
updatedAppCredentials =
await AndroidAppCredentialsMutation.setGoogleServiceAccountKeyForFcmV1Async(
graphqlClient,
appCredentials.id,
googleServiceAccountKeyForFcmV1Id
);
}
return updatedAppCredentials;
}
@@ -8,6 +8,7 @@ import {
CommonAndroidAppCredentialsFragment,
CreateAndroidAppCredentialsMutation,
SetFcmMutation,
SetGoogleServiceAccountKeyForFcmV1Mutation,
SetGoogleServiceAccountKeyForSubmissionsMutation,
} from '../../../../../graphql/generated';
import { CommonAndroidAppCredentialsFragmentNode } from '../../../../../graphql/types/credentials/AndroidAppCredentials';
@@ -124,4 +125,42 @@ 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) Key abcd...efgh
Updated 0 second agoGoogle Service Account Key For Submissions Project ID sdf.sdf.sdf
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
Client Email [email protected]
Client ID test-client-identifier
Private Key ID test-private-key-identifier
@@ -13,7 +13,11 @@ 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) } }));
jest.mock('chalk', () => ({
bold: jest.fn(log => log),
cyan: { bold: jest.fn(log => log) },
dim: 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'],
ignore: ['app.json', 'package*.json', 'tsconfig.json', 'node_modules', 'google-services.json'],
});
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)', value: '' }], {
formatFields([{ label: 'Push Notifications (FCM Legacy)', value: '' }], {
labelFormat: chalk.cyan.bold,
})
);
@@ -60,9 +60,43 @@ function displayGoogleServiceAccountKeyForSubmissions(
): void {
const maybeGsaKey = appCredentials.googleServiceAccountKeyForSubmissions;
Log.log(
formatFields([{ label: 'Google Service Account Key For Submissions', value: '' }], {
labelFormat: chalk.cyan.bold,
})
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,
}
)
);
if (!maybeGsaKey) {
Log.log(formatFields([{ label: '', value: 'None assigned yet' }]));
@@ -87,6 +121,7 @@ function displayEASAndroidAppCredentials(
appCredentials: CommonAndroidAppCredentialsFragment
): void {
displayAndroidFcmCredentials(appCredentials);
displayGoogleServiceAccountKeyForFcmV1(appCredentials);
displayGoogleServiceAccountKeyForSubmissions(appCredentials);
const sortedBuildCredentialsList = sortBuildCredentials(
appCredentials.androidAppBuildCredentialsList
@@ -1,6 +1,5 @@
import { AppStoreApiKeyPurpose, provideOrGenerateAscApiKeyAsync } from './AscApiKeyUtils';
import { AccountFragment, AppStoreConnectApiKeyFragment } from '../../../graphql/generated';
import Log from '../../../log';
import { CredentialsContext } from '../../context';
export class CreateAscApiKey {
@@ -15,8 +14,6 @@ export class CreateAscApiKey {
}
const ascApiKey = await provideOrGenerateAscApiKeyAsync(ctx, purpose);
const result = await ctx.ios.createAscApiKeyAsync(ctx.graphqlClient, this.account, ascApiKey);
Log.succeed('Created App Store Connect API Key');
return result;
return await ctx.ios.createAscApiKeyAsync(ctx.graphqlClient, this.account, ascApiKey);
}
}
@@ -13,7 +13,9 @@ export enum Scope {
export enum AndroidActionType {
ManageBuildCredentials,
ManageFcm,
ManageGoogleServiceAccountKey,
ManageGoogleServiceAccountKeyForSubmissions,
ManageGoogleServiceAccount,
ManageGoogleServiceAccountKeyForFcmV1,
ManageCredentialsJson,
GoBackToCaller,
GoBackToHighLevelActions,
@@ -24,9 +26,13 @@ export enum AndroidActionType {
CreateFcm,
RemoveFcm,
CreateGsaKey,
UseExistingGsaKey,
UseExistingGsaKeyForSubmissions,
RemoveGsaKey,
SetUpGsaKey,
SetUpGsaKeyForSubmissions,
CreateGsaKeyForFcmV1,
UseExistingGsaKeyForFcmV1,
RemoveGsaKeyForFcmV1,
SetUpGsaKeyForFcmV1,
UpdateCredentialsJson,
SetUpBuildCredentialsFromCredentialsJson,
}
@@ -7,13 +7,13 @@ export const highLevelActions: ActionInfo[] = [
scope: Scope.Manager,
},
{
value: AndroidActionType.ManageFcm,
title: 'Push Notifications: Manage your FCM API Key',
value: AndroidActionType.ManageGoogleServiceAccount,
title: 'Google Service Account',
scope: Scope.Manager,
},
{
value: AndroidActionType.ManageGoogleServiceAccountKey,
title: 'Google Service Account: Manage your Service Account Key',
value: AndroidActionType.ManageFcm,
title: 'Push Notifications (Legacy): Manage your FCM (Legacy) API Key',
scope: Scope.Manager,
},
{
@@ -92,22 +92,58 @@ export const fcmActions: ActionInfo[] = [
},
];
export const gsaKeyActions: ActionInfo[] = [
export const gsaKeyActionsForFcmV1: ActionInfo[] = [
{
value: AndroidActionType.SetUpGsaKey,
title: 'Set up a Google Service Account Key',
value: AndroidActionType.SetUpGsaKeyForFcmV1,
title: 'Set up a Google Service Account Key for Push Notifications (FCM V1)',
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,7 +7,9 @@ import {
buildCredentialsActions,
credentialsJsonActions,
fcmActions,
gsaKeyActions,
gsaActions,
gsaKeyActionsForFcmV1,
gsaKeyActionsForSubmissions,
highLevelActions,
} from './AndroidActions';
import { CreateAndroidBuildCredentials } from './CreateAndroidBuildCredentials';
@@ -19,7 +21,8 @@ import Log, { learnMore } from '../../log';
import { GradleBuildContext, resolveGradleBuildContextAsync } from '../../project/android/gradle';
import { promptAsync } from '../../prompts';
import { AssignFcm } from '../android/actions/AssignFcm';
import { AssignGoogleServiceAccountKey } from '../android/actions/AssignGoogleServiceAccountKey';
import { AssignGoogleServiceAccountKeyForFcmV1 } from '../android/actions/AssignGoogleServiceAccountKeyForFcmV1';
import { AssignGoogleServiceAccountKeyForSubmissions } from '../android/actions/AssignGoogleServiceAccountKeyForSubmissions';
import {
canCopyLegacyCredentialsAsync,
getAppLookupParamsFromContextAsync,
@@ -32,7 +35,8 @@ 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 { SetUpGoogleServiceAccountKey } from '../android/actions/SetUpGoogleServiceAccountKey';
import { SetUpGoogleServiceAccountKeyForFcmV1 } from '../android/actions/SetUpGoogleServiceAccountKeyForFcmV1';
import { SetUpGoogleServiceAccountKeyForSubmissions } from '../android/actions/SetUpGoogleServiceAccountKeyForSubmissions';
import { UpdateCredentialsJson } from '../android/actions/UpdateCredentialsJson';
import { UseExistingGoogleServiceAccountKey } from '../android/actions/UseExistingGoogleServiceAccountKey';
import {
@@ -120,8 +124,16 @@ export class ManageAndroid {
} else if (chosenAction === AndroidActionType.ManageFcm) {
currentActions = fcmActions;
continue;
} else if (chosenAction === AndroidActionType.ManageGoogleServiceAccountKey) {
currentActions = gsaKeyActions;
} else if (chosenAction === AndroidActionType.ManageGoogleServiceAccount) {
currentActions = gsaActions;
continue;
} else if (
chosenAction === AndroidActionType.ManageGoogleServiceAccountKeyForSubmissions
) {
currentActions = gsaKeyActionsForSubmissions;
continue;
} else if (chosenAction === AndroidActionType.ManageGoogleServiceAccountKeyForFcmV1) {
currentActions = gsaKeyActionsForFcmV1;
continue;
} else if (chosenAction === AndroidActionType.ManageCredentialsJson) {
currentActions = credentialsJsonActions;
@@ -193,20 +205,31 @@ 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.CreateGsaKey) {
const gsaKey = await new CreateGoogleServiceAccountKey(appLookupParams.account).runAsync(ctx);
await new AssignGoogleServiceAccountKey(appLookupParams).runAsync(ctx, gsaKey);
} else if (action === AndroidActionType.UseExistingGsaKey) {
} 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 AssignGoogleServiceAccountKey(appLookupParams).runAsync(ctx, 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);
} 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' },
app: { exp: testAppJson, projectId: 'test-project-id', projectDir: '/' },
};
}
+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 };
app: { exp: ExpoConfig; projectId: string; projectDir: string };
};
export interface EASUpdateAction<T = any> {
+55 -14
View File
@@ -759,6 +759,7 @@ 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'];
@@ -771,6 +772,7 @@ export type AndroidAppCredentialsFilter = {
export type AndroidAppCredentialsInput = {
fcmId?: InputMaybe<Scalars['ID']['input']>;
googleServiceAccountKeyForFcmV1Id?: InputMaybe<Scalars['ID']['input']>;
googleServiceAccountKeyForSubmissionsId?: InputMaybe<Scalars['ID']['input']>;
};
@@ -778,10 +780,17 @@ 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;
};
@@ -794,6 +803,13 @@ 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'];
};
@@ -805,6 +821,12 @@ 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'];
@@ -2117,6 +2139,7 @@ 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']>;
@@ -2282,6 +2305,7 @@ export type BuildFilter = {
platform?: InputMaybe<AppPlatform>;
runtimeVersion?: InputMaybe<Scalars['String']['input']>;
sdkVersion?: InputMaybe<Scalars['String']['input']>;
simulator?: InputMaybe<Scalars['Boolean']['input']>;
status?: InputMaybe<BuildStatus>;
};
@@ -2291,6 +2315,7 @@ export type BuildFilterInput = {
distributions?: InputMaybe<Array<DistributionType>>;
platforms?: InputMaybe<Array<AppPlatform>>;
releaseChannel?: InputMaybe<Scalars['String']['input']>;
simulator?: InputMaybe<Scalars['Boolean']['input']>;
};
export enum BuildIosEnterpriseProvisioning {
@@ -2408,6 +2433,7 @@ 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>;
@@ -2588,6 +2614,7 @@ export type BuildPublicData = {
artifacts: PublicArtifacts;
distribution?: Maybe<DistributionType>;
id: Scalars['ID']['output'];
isForIosSimulator: Scalars['Boolean']['output'];
platform: AppPlatform;
project: ProjectPublicData;
status: BuildStatus;
@@ -2791,6 +2818,7 @@ 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;
@@ -3371,6 +3399,7 @@ 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'];
@@ -3939,6 +3968,7 @@ 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'
}
@@ -4106,9 +4136,11 @@ 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'
}
@@ -5334,6 +5366,7 @@ 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;
};
@@ -6110,7 +6143,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, 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, 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 SetFcmMutationVariables = Exact<{
androidAppCredentialsId: Scalars['ID']['input'];
@@ -6118,7 +6151,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, 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, 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 SetGoogleServiceAccountKeyForSubmissionsMutationVariables = Exact<{
androidAppCredentialsId: Scalars['ID']['input'];
@@ -6126,7 +6159,15 @@ 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, 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, 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 CreateAndroidFcmMutationVariables = Exact<{
androidFcmInput: AndroidFcmInput;
@@ -6180,7 +6221,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, 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, 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 GoogleServiceAccountKeyByAccountQueryVariables = Exact<{
accountName: Scalars['String']['input'];
@@ -6492,7 +6533,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, 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, 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 CreateIosBuildMutationVariables = Exact<{
appId: Scalars['ID']['input'];
@@ -6502,7 +6543,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, 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, 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 UpdateBuildMetadataMutationVariables = Exact<{
buildId: Scalars['ID']['input'];
@@ -6510,7 +6551,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, 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, 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 RetryIosBuildMutationVariables = Exact<{
buildId: Scalars['ID']['input'];
@@ -6518,7 +6559,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, 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, 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 CreateEnvironmentSecretForAccountMutationVariables = Exact<{
input: CreateEnvironmentSecretInput;
@@ -6686,14 +6727,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, 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, 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 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, 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, 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 ViewBuildsOnAppQueryVariables = Exact<{
appId: Scalars['String']['input'];
@@ -6703,7 +6744,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, 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, 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 ViewUpdateChannelOnAppQueryVariables = Exact<{
appId: Scalars['String']['input'];
@@ -6845,9 +6886,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, 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, isForIosSimulator: boolean, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } };
export type BuildWithSubmissionsFragment = { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, 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 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 EnvironmentSecretFragment = { __typename?: 'EnvironmentSecret', id: string, name: string, type: EnvironmentSecretType, createdAt: any };
@@ -6869,7 +6910,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, 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, 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 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,6 +57,7 @@ export const BuildFragmentNode = gql`
completedAt
resourceClass
expirationDate
isForIosSimulator
}
`;
@@ -18,6 +18,10 @@ export const CommonAndroidAppCredentialsFragmentNode = gql`
id
...AndroidFcmFragment
}
googleServiceAccountKeyForFcmV1 {
id
...GoogleServiceAccountKeyFragment
}
googleServiceAccountKeyForSubmissions {
id
...GoogleServiceAccountKeyFragment
@@ -41,7 +41,7 @@ export async function validateCustomBuildConfigAsync({
try {
const config = await readAndValidateBuildConfigAsync(configPath, {
skipNamespacedFunctionsCheck: true,
skipNamespacedFunctionsOrFunctionGroupsCheck: true,
});
return {
workflowName: config.build.name,
+54 -13
View File
@@ -88,6 +88,17 @@ 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
@@ -96,12 +107,13 @@ export async function validateAppVersionRuntimePolicySupportAsync(
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;
}
const expoUpdatesPackageVersion = await getExpoUpdatesPackageVersionIfInstalledAsync(projectDir);
if (
expoUpdatesPackageVersion !== null &&
(semver.gte(expoUpdatesPackageVersion, '0.14.4') ||
expoUpdatesPackageVersion.includes('canary'))
) {
return;
}
Log.warn(
@@ -112,13 +124,13 @@ export async function validateAppVersionRuntimePolicySupportAsync(
export async function enforceRollBackToEmbeddedUpdateSupportAsync(
projectDir: string
): Promise<void> {
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;
}
const expoUpdatesPackageVersion = await getExpoUpdatesPackageVersionIfInstalledAsync(projectDir);
if (
expoUpdatesPackageVersion !== null &&
(semver.gte(expoUpdatesPackageVersion, '0.19.0') ||
expoUpdatesPackageVersion.includes('canary'))
) {
return;
}
throw new Error(
@@ -128,6 +140,35 @@ 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 }
+96 -58
View File
@@ -12,6 +12,7 @@ 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';
@@ -24,17 +25,17 @@ import Log, { learnMore } from '../log';
import { RequestedPlatform, requestedPlatformDisplayNames } from '../platform';
import { promptAsync } from '../prompts';
import { getBranchNameFromChannelNameAsync } from '../update/getBranchNameFromChannelNameAsync';
import {
UpdateJsonInfo,
formatUpdateMessage,
truncateString as truncateUpdateMessage,
} from '../update/utils';
import { 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';
@@ -189,14 +190,12 @@ 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) {
@@ -214,7 +213,6 @@ export async function buildBundlesAsync({
'--dump-sourcemap',
'--dump-assetmap',
`--platform=${platformFlag}`,
...(dev ? ['--dev'] : []),
...(clearCache ? ['--clear'] : []),
]);
}
@@ -234,7 +232,6 @@ export async function buildBundlesAsync({
'--dump-sourcemap',
'--dump-assetmap',
...platformArgs,
...(dev ? ['--dev'] : []),
...(clearCache ? ['--clear'] : []),
]);
}
@@ -256,7 +253,6 @@ export async function buildBundlesAsync({
'--dump-sourcemap',
'--dump-assetmap',
`--platform=${platformFlag}`,
...(dev ? ['--dev'] : []),
...(clearCache ? ['--clear'] : []),
]);
}
@@ -298,14 +294,6 @@ 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
@@ -575,12 +563,7 @@ export async function getBranchNameForCommandAsync({
}
if (channelNameArg) {
return await getBranchNameFromChannelNameAsync(
graphqlClient,
projectId,
channelNameArg,
paginatedQueryOptions
);
return await getBranchNameFromChannelNameAsync(graphqlClient, projectId, channelNameArg);
}
if (branchNameArg) {
@@ -697,45 +680,100 @@ 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: 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'
)}`
);
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';
}
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,
`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;
}
}
}
return [...new Set(platforms)].map(platform => {
if (platform === 'web') {
return { platform: 'web', runtimeVersion: 'UNVERSIONED' };
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'
)}`
);
}
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/')}`
),
};
});
}
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(
@@ -0,0 +1,45 @@
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,4 +1,3 @@
import { Updates } from '@expo/config-plugins';
import assert from 'assert';
import { SelectRuntime } from './SelectRuntime';
@@ -24,6 +23,7 @@ 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,9 +272,13 @@ export class CreateRollout implements EASUpdateAction<UpdateChannelBasicInfoFrag
async selectRuntimeVersionFromProjectConfigAsync(ctx: EASUpdateContext): Promise<string> {
const platforms: ('ios' | 'android')[] = ['ios', 'android'];
const runtimes = platforms
.map(platform => Updates.getRuntimeVersion(ctx.app.exp, platform))
.filter(truthy);
const runtimes = (
await Promise.all(
platforms.map(platform =>
resolveRuntimeVersionAsync({ projectDir: ctx.app.projectDir, exp: 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, DistributionType } from '../graphql/generated';
import { AppPlatform, BuildFragment, BuildStatus } 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.distribution === DistributionType.Simulator) ||
((build.platform === AppPlatform.Ios && build.isForIosSimulator) ||
(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 { SetUpGoogleServiceAccountKey } from '../../credentials/android/actions/SetUpGoogleServiceAccountKey';
import { SetUpGoogleServiceAccountKeyForSubmissions } from '../../credentials/android/actions/SetUpGoogleServiceAccountKeyForSubmissions';
import { readAndValidateServiceAccountKey } from '../../credentials/android/utils/googleServiceAccountKey';
import Log, { learnMore } from '../../log';
import {
@@ -126,7 +126,9 @@ export async function getServiceAccountFromCredentialsServiceAsync(
Log.log(
`Looking up credentials configuration for ${appLookupParams.androidApplicationIdentifier}...`
);
const setupGoogleServiceAccountKeyAction = new SetUpGoogleServiceAccountKey(appLookupParams);
const setupGoogleServiceAccountKeyAction = new SetUpGoogleServiceAccountKeyForSubmissions(
appLookupParams
);
const androidAppCredentials = await setupGoogleServiceAccountKeyAction.runAsync(
ctx.credentialsCtx
);
@@ -11,7 +11,7 @@ import {
jester as mockJester,
testProjectId,
} from '../../../credentials/__tests__/fixtures-constants';
import { SetUpGoogleServiceAccountKey } from '../../../credentials/android/actions/SetUpGoogleServiceAccountKey';
import { SetUpGoogleServiceAccountKeyForSubmissions } from '../../../credentials/android/actions/SetUpGoogleServiceAccountKeyForSubmissions';
import { createTestProject } from '../../../project/__tests__/project-utils';
import { getOwnerAccountForProjectIdAsync } from '../../../project/projectUtils';
import { promptAsync } from '../../../prompts';
@@ -27,7 +27,7 @@ import {
jest.mock('fs');
jest.mock('../../../prompts');
jest.mock('../../../project/projectUtils');
jest.mock('../../../credentials/android/actions/SetUpGoogleServiceAccountKey');
jest.mock('../../../credentials/android/actions/SetUpGoogleServiceAccountKeyForSubmissions');
jest.mock('../../../user/User', () => ({
getUserAsync: jest.fn(() => mockJester),
}));
@@ -55,7 +55,7 @@ beforeAll(() => {
'/other_dir/invalid_file.txt': 'this is not even a JSON',
});
jest
.spyOn(SetUpGoogleServiceAccountKey.prototype, 'runAsync')
.spyOn(SetUpGoogleServiceAccountKeyForSubmissions.prototype, 'runAsync')
.mockImplementation(async () => testAndroidAppCredentialsFragment);
});
afterAll(() => {
@@ -111,6 +111,11 @@ 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,
@@ -78,6 +78,43 @@ 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();
@@ -118,7 +155,7 @@ describe(IosSubmitCommand, () => {
.mocked(getArchiveAsync)
.mockImplementation(jest.requireActual('../../ArchiveSource').getArchiveAsync);
process.env.EXPO_APPLE_APP_SPECIFIC_PASSWORD = 'supersecret';
process.env.EXPO_APPLE_APP_SPECIFIC_PASSWORD = 'abcd-abcd-abcd-abcd';
const ctx = await createSubmissionContextAsync({
platform: Platform.IOS,
@@ -147,7 +184,7 @@ describe(IosSubmitCommand, () => {
archiveSource: { type: SubmissionArchiveSourceType.Url, url: 'http://expo.dev/fake.ipa' },
config: {
appleIdUsername: '[email protected]',
appleAppSpecificPassword: 'supersecret',
appleAppSpecificPassword: 'abcd-abcd-abcd-abcd',
ascAppIdentifier: '12345678',
},
});
@@ -182,7 +219,7 @@ describe(IosSubmitCommand, () => {
return ctx;
});
process.env.EXPO_APPLE_APP_SPECIFIC_PASSWORD = 'supersecret';
process.env.EXPO_APPLE_APP_SPECIFIC_PASSWORD = 'abcd-abcd-abcd-abcd';
const ctx = await createSubmissionContextAsync({
platform: Platform.IOS,
@@ -209,7 +246,7 @@ describe(IosSubmitCommand, () => {
submittedBuildId: selectedBuild.id,
config: {
appleIdUsername: '[email protected]',
appleAppSpecificPassword: 'supersecret',
appleAppSpecificPassword: 'abcd-abcd-abcd-abcd',
ascAppIdentifier: '87654321',
},
archiveSource: undefined,
@@ -239,7 +276,7 @@ describe(IosSubmitCommand, () => {
return ctx;
});
process.env.EXPO_APPLE_APP_SPECIFIC_PASSWORD = 'supersecret';
process.env.EXPO_APPLE_APP_SPECIFIC_PASSWORD = 'abcd-abcd-abcd-abcd';
const ctx = await createSubmissionContextAsync({
platform: Platform.IOS,
@@ -266,7 +303,7 @@ describe(IosSubmitCommand, () => {
submittedBuildId: selectedBuild.id,
config: {
appleIdUsername: '[email protected]',
appleAppSpecificPassword: 'supersecret',
appleAppSpecificPassword: 'abcd-abcd-abcd-abcd',
ascAppIdentifier: '12345678',
},
archiveSource: undefined,
@@ -301,7 +338,7 @@ describe(IosSubmitCommand, () => {
return ctx;
});
process.env.EXPO_APPLE_APP_SPECIFIC_PASSWORD = 'supersecret';
process.env.EXPO_APPLE_APP_SPECIFIC_PASSWORD = 'abcd-abcd-abcd-abcd';
const ctx = await createSubmissionContextAsync({
platform: Platform.IOS,
@@ -329,7 +366,7 @@ describe(IosSubmitCommand, () => {
submittedBuildId: selectedBuild.id,
config: {
appleIdUsername: '[email protected]',
appleAppSpecificPassword: 'supersecret',
appleAppSpecificPassword: 'abcd-abcd-abcd-abcd',
ascAppIdentifier: '12345678',
},
archiveSource: undefined,
@@ -1,22 +1,13 @@
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();
@@ -35,14 +26,13 @@ describe(getBranchNameFromChannelNameAsync, () => {
const result = await getBranchNameFromChannelNameAsync(
graphqlClient,
'test-project-id',
'channel-name',
defaultPaginatedQueryOptions
'channel-name'
);
expect(result).toBe('test-branch-name');
});
test('prompts user to select a branch if no branch is connected to channel', async () => {
test('errors when no branch is connected to channel', async () => {
const graphqlClient = instance(mock<ExpoGraphqlClient>());
jest.mocked(ChannelQuery.viewUpdateChannelAsync).mockImplementationOnce(
async () =>
@@ -51,24 +41,11 @@ describe(getBranchNameFromChannelNameAsync, () => {
}) as any
);
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
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"
);
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 () => {
@@ -82,12 +59,7 @@ describe(getBranchNameFromChannelNameAsync, () => {
);
expect(
getBranchNameFromChannelNameAsync(
graphqlClient,
'test-project-id',
'test-channel-name',
defaultPaginatedQueryOptions
)
getBranchNameFromChannelNameAsync(graphqlClient, 'test-project-id', 'test-channel-name')
).rejects.toThrow(
"Channel has multiple branches associated with it. Instead, use '--branch' instead of '--channel'"
);
@@ -106,8 +78,7 @@ describe(getBranchNameFromChannelNameAsync, () => {
const result = await getBranchNameFromChannelNameAsync(
graphqlClient,
'test-project-id',
'test-channel-name',
defaultPaginatedQueryOptions
'test-channel-name'
);
expect(result).toBe('test-branch-name');
@@ -1,31 +1,36 @@
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 { getOwnerAccountForProjectIdAsync } from '../../project/projectUtils';
import { isModernExpoUpdatesCLIWithRuntimeVersionCommandSupportedAsync } from '../../project/projectUtils';
import { expoUpdatesCommandAsync } from '../../utils/expoUpdatesCli';
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,
projectId: string
exp: ExpoConfig
): Promise<void> {
ensureValidVersions(exp, RequestedPlatform.Android);
const accountName = (await getOwnerAccountForProjectIdAsync(graphqlClient, projectId)).name;
if (await isModernExpoUpdatesCLIWithRuntimeVersionCommandSupportedAsync(projectDir)) {
await expoUpdatesCommandAsync(projectDir, [
'configuration:syncnative',
'--platform',
'android',
]);
return;
}
// sync AndroidManifest.xml
const androidManifestPath = await AndroidConfig.Paths.getAndroidManifestAsync(projectDir);
const androidManifest = await getAndroidManifestAsync(projectDir);
const updatedAndroidManifest = AndroidConfig.Updates.setUpdatesConfig(
const updatedAndroidManifest = await AndroidConfig.Updates.setUpdatesConfigAsync(
projectDir,
exp,
androidManifest,
accountName
androidManifest
);
await AndroidConfig.Manifest.writeAndroidManifestAsync(
androidManifestPath,
@@ -37,10 +42,14 @@ export async function syncUpdatesConfigurationAsync(
const stringsResourceXML = await AndroidConfig.Resources.readResourcesXMLAsync({
path: stringsJSONPath,
});
const updatedStringsResourceXML = AndroidConfig.Updates.applyRuntimeVersionFromConfig(
exp,
stringsResourceXML
);
// TODO(wschurman): this dependency needs to be updated for fingerprint
const updatedStringsResourceXML =
await AndroidConfig.Updates.applyRuntimeVersionFromConfigForProjectRootAsync(
projectDir,
exp,
stringsResourceXML
);
await XML.writeXMLAsync({ path: stringsJSONPath, xml: updatedStringsResourceXML });
}
+18 -81
View File
@@ -8,18 +8,16 @@ 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, isUsingStaticExpoConfig } from '../project/expoConfig';
import { createOrModifyExpoConfigAsync } 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;
@@ -233,7 +231,7 @@ function warnEASUpdatesManualConfig({
)}`
);
Log.warn(
`Finish configuring EAS Update by adding the following to the project app.config.js:\n${learnMore(
`Add the following EAS Update key-values to the project app.config.js:\n${learnMore(
'https://expo.fyi/eas-update-config'
)}\n`
);
@@ -260,29 +258,26 @@ 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(graphqlClient, projectDir, exp, projectId);
await syncAndroidUpdatesConfigurationAsync(projectDir, exp);
Log.withTick(`Configured ${chalk.bold('AndroidManifest.xml')} for EAS Update`);
}
if (['all', 'ios'].includes(platform) && workflows.ios === Workflow.GENERIC) {
await syncIosUpdatesConfigurationAsync(graphqlClient, vcsClient, projectDir, exp, projectId);
await syncIosUpdatesConfigurationAsync(vcsClient, projectDir, exp);
Log.withTick(`Configured ${chalk.bold('Expo.plist')} for EAS Update`);
}
}
@@ -356,30 +351,19 @@ 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(
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,
});
}
export async function ensureEASUpdateIsConfiguredAsync({
exp: expMaybeWithoutUpdates,
projectId,
projectDir,
vcsClient,
platform,
}: {
exp: ExpoConfig;
projectId: string;
projectDir: string;
vcsClient: Client;
platform: RequestedPlatform | null;
}): Promise<void> {
const hasExpoUpdates = isExpoUpdatesInstalledOrAvailable(
projectDir,
expMaybeWithoutUpdates.sdkVersion
@@ -411,10 +395,9 @@ export async function ensureEASUpdateIsConfiguredAsync(
});
if (projectChanged || !hasExpoUpdates) {
await ensureEASUpdateIsConfiguredNativelyAsync(graphqlClient, vcsClient, {
await ensureEASUpdateIsConfiguredNativelyAsync(vcsClient, {
exp: expWithUpdates,
projectDir,
projectId,
platform,
workflows,
});
@@ -428,49 +411,3 @@ 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,18 +1,13 @@
import { ensureBranchExistsAsync, selectBranchOnAppAsync } from '../branch/queries';
import { getAlwaysTrueBranchMapping } from '../channel/branch-mapping';
import { ensureBranchExistsAsync } from '../branch/queries';
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,
paginatedQueryOptions: PaginatedQueryOptions
channelName: string
): Promise<string> {
let branchName;
@@ -25,19 +20,9 @@ export async function getBranchNameFromChannelNameAsync(
if (channel.updateBranches.length === 1) {
branchName = channel.updateBranches[0].name;
} else if (channel.updateBranches.length === 0) {
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;
throw new Error(
"Channel has no branches associated with it. Run 'eas channel:edit' to map a branch"
);
} else {
throw new Error(
`Channel has multiple branches associated with it. Instead, use '--branch' instead of '--channel'`
@@ -1,28 +1,31 @@
import { ExpoConfig } from '@expo/config';
import { IOSConfig } from '@expo/config-plugins';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { RequestedPlatform } from '../../platform';
import { getOwnerAccountForProjectIdAsync } from '../../project/projectUtils';
import { isModernExpoUpdatesCLIWithRuntimeVersionCommandSupportedAsync } from '../../project/projectUtils';
import { expoUpdatesCommandAsync } from '../../utils/expoUpdatesCli';
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,
projectId: string
exp: ExpoConfig
): Promise<void> {
ensureValidVersions(exp, RequestedPlatform.Ios);
const accountName = (await getOwnerAccountForProjectIdAsync(graphqlClient, projectId)).name;
if (await isModernExpoUpdatesCLIWithRuntimeVersionCommandSupportedAsync(projectDir)) {
await expoUpdatesCommandAsync(projectDir, ['configuration:syncnative', '--platform', 'ios']);
return;
}
const expoPlist = await readExpoPlistAsync(projectDir);
const updatedExpoPlist = IOSConfig.Updates.setUpdatesConfig(
// TODO(wschurman): this dependency needs to be updated for fingerprint
const updatedExpoPlist = await IOSConfig.Updates.setUpdatesConfigAsync(
projectDir,
exp,
expoPlist,
accountName
expoPlist
);
await writeExpoPlistAsync(vcsClient, projectDir, updatedExpoPlist);
}
@@ -0,0 +1,36 @@
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;
}
}
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "@expo/eas-json",
"description": "A library for interacting with eas.json",
"version": "6.0.0",
"version": "7.4.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.56",
"@expo/eas-build-job": "1.0.78",
"chalk": "4.1.2",
"env-string": "1.0.1",
"fs-extra": "11.2.0",
+77 -14
View File
@@ -24,14 +24,19 @@
"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.",
@@ -102,7 +107,10 @@
"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",
@@ -124,7 +132,10 @@
"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": [
@@ -203,13 +214,21 @@
"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"
},
@@ -263,7 +282,11 @@
"default": "default",
"anyOf": [
{
"enum": ["default", "medium", "large"]
"enum": [
"default",
"medium",
"large"
]
},
{
"type": "string"
@@ -275,7 +298,12 @@
"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,
@@ -287,7 +315,10 @@
]
},
"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": [
@@ -311,6 +342,10 @@
"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"
}
}
},
@@ -330,14 +365,22 @@
"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,
@@ -357,6 +400,7 @@
"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",
@@ -367,7 +411,7 @@
],
"markdownEnumDescriptions": [
"`macos-ventura-13.4-xcode-14.3.1`",
"`macos-ventura-13.6-xcode-15.1`"
"`macos-ventura-13.6-xcode-15.2`"
]
},
{
@@ -391,7 +435,12 @@
"default": "default",
"anyOf": [
{
"enum": ["default", "medium", "large", "m-medium"]
"enum": [
"default",
"medium",
"large",
"m-medium"
]
},
{
"type": "string"
@@ -432,6 +481,10 @@
"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"
}
}
},
@@ -471,7 +524,12 @@
"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": [
@@ -482,7 +540,12 @@
]
},
"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: 'QWERTY',
appleTeamId: 'AB32CZE81F',
ascApiKeyPath: './path-ABCD.p8',
ascApiKeyIssuerId: 'abc-123-def-456',
ascApiKeyId: 'ABCD',
ascApiKeyIssuerId: 'b4d78f58-48c6-4f2c-96cb-94d8cd76970a',
ascApiKeyId: 'AB32CZE81F',
},
},
},
@@ -121,11 +121,11 @@ test('ios config with all required values', async () => {
expect(iosProfile).toEqual({
appleId: '[email protected]',
appleTeamId: 'QWERTY',
appleTeamId: 'AB32CZE81F',
ascAppId: '1223423523',
ascApiKeyPath: './path-ABCD.p8',
ascApiKeyIssuerId: 'abc-123-def-456',
ascApiKeyId: 'ABCD',
ascApiKeyIssuerId: 'b4d78f58-48c6-4f2c-96cb-94d8cd76970a',
ascApiKeyId: 'AB32CZE81F',
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: 'QWERTY',
appleTeamId: 'AB32CZE81F',
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 = 'abc-123-def-456';
process.env.ASC_API_KEY_ID = 'ABCD';
process.env.ASC_API_KEY_ISSUER_ID = 'b4d78f58-48c6-4f2c-96cb-94d8cd76970a';
process.env.ASC_API_KEY_ID = 'AB32CZE81F';
const accessor = EasJsonAccessor.fromProjectPath('/project');
const iosProfile = await EasJsonUtils.getSubmitProfileAsync(accessor, Platform.IOS, 'release');
expect(iosProfile).toEqual({
appleId: '[email protected]',
ascAppId: '1223423523',
appleTeamId: 'QWERTY',
appleTeamId: 'AB32CZE81F',
ascApiKeyPath: './path-ABCD.p8',
ascApiKeyIssuerId: 'abc-123-def-456',
ascApiKeyId: 'ABCD',
ascApiKeyIssuerId: 'b4d78f58-48c6-4f2c-96cb-94d8cd76970a',
ascApiKeyId: 'AB32CZE81F',
language: 'en-US',
});
} finally {
@@ -176,16 +176,16 @@ test('valid profile extending other profile', async () => {
ios: {
appleId: '[email protected]',
ascAppId: '1223423523',
appleTeamId: 'QWERTY',
appleTeamId: 'AB32CZE81F',
},
},
extension: {
extends: 'base',
ios: {
appleTeamId: 'ABCDEF',
appleTeamId: 'AB32CZE81F',
ascApiKeyPath: './path-ABCD.p8',
ascApiKeyIssuerId: 'abc-123-def-456',
ascApiKeyId: 'ABCD',
ascApiKeyIssuerId: '2af70a7a-2ac5-44d4-924e-ae97a7ca9333',
ascApiKeyId: 'AB32CZE81F',
},
},
},
@@ -202,19 +202,134 @@ test('valid profile extending other profile', async () => {
language: 'en-US',
appleId: '[email protected]',
ascAppId: '1223423523',
appleTeamId: 'QWERTY',
appleTeamId: 'AB32CZE81F',
});
expect(extendedProfile).toEqual({
language: 'en-US',
appleId: '[email protected]',
ascAppId: '1223423523',
appleTeamId: 'ABCDEF',
appleTeamId: 'AB32CZE81F',
ascApiKeyPath: './path-ABCD.p8',
ascApiKeyIssuerId: 'abc-123-def-456',
ascApiKeyId: 'ABCD',
ascApiKeyIssuerId: '2af70a7a-2ac5-44d4-924e-ae97a7ca9333',
ascApiKeyId: 'AB32CZE81F',
});
});
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 { SubmitProfileSchema } from './submit/schema';
import { UnresolvedSubmitProfileSchema } 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(), SubmitProfileSchema),
submit: Joi.object().pattern(Joi.string(), UnresolvedSubmitProfileSchema),
});
+2 -2
View File
@@ -1,7 +1,7 @@
import { Platform } from '@expo/eas-build-job';
import envString from 'env-string';
import { AndroidSubmitProfileSchema, IosSubmitProfileSchema } from './schema';
import { AndroidSubmitProfileSchema, ResolvedIosSubmitProfileSchema } 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 : IosSubmitProfileSchema;
platform === Platform.ANDROID ? AndroidSubmitProfileSchema : ResolvedIosSubmitProfileSchema;
return Schema.validate({}, { allowUnknown: false, abortEarly: false, convert: true }).value;
}
+43 -3
View File
@@ -19,7 +19,9 @@ export const AndroidSubmitProfileSchema = Joi.object({
}),
});
export const IosSubmitProfileSchema = 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({
ascApiKeyPath: Joi.string(),
ascApiKeyId: Joi.string(),
ascApiKeyIssuerId: Joi.string(),
@@ -34,8 +36,46 @@ export const IosSubmitProfileSchema = Joi.object({
metadataPath: Joi.string(),
});
export const SubmitProfileSchema = Joi.object({
// 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({
extends: Joi.string(),
android: AndroidSubmitProfileSchema,
ios: IosSubmitProfileSchema,
ios: UnresolvedIosSubmitProfileSchema,
});
+13 -1
View File
@@ -5,6 +5,7 @@ import { resolveBuildProfile } from './build/resolver';
import { BuildProfile } from './build/types';
import { MissingEasJsonError } from './errors';
import { resolveSubmitProfile } from './submit/resolver';
import { AndroidSubmitProfileSchema, ResolvedIosSubmitProfileSchema } from './submit/schema';
import { SubmitProfile } from './submit/types';
import { EasJson } from './types';
@@ -102,6 +103,17 @@ export class EasJsonUtils {
profileName?: string
): Promise<SubmitProfile<T>> {
const easJson = await accessor.readAsync();
return resolveSubmitProfile({ easJson, platform, profileName });
const profile = resolveSubmitProfile({ easJson, platform, profileName });
const Schema =
platform === Platform.ANDROID ? AndroidSubmitProfileSchema : ResolvedIosSubmitProfileSchema;
const { value, error } = Schema.validate(profile, {
allowUnknown: false,
abortEarly: false,
convert: true,
});
if (error) {
throw error;
}
return value;
}
}
Generated
+222 -88
View File
@@ -1354,10 +1354,10 @@
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.56.0.tgz#ef20350fec605a7f7035a01764731b2de0f3782b"
integrity sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==
"@expo/apple-utils@1.3.2":
version "1.3.2"
resolved "https://registry.yarnpkg.com/@expo/apple-utils/-/apple-utils-1.3.2.tgz#c2c80e03bb4c310e183b109ea37bbc88cef59313"
integrity sha512-8utf2r+ka9uI1qhazBEbLzjPX0CIBvvpBHy0o4XFoLUiZDvBqGBEctduvJc49hvu/16hxVtNqGXs1U97OVKe4g==
"@expo/apple-utils@1.5.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@expo/apple-utils/-/apple-utils-1.5.0.tgz#1ba5ffb946f5d4a5109efaaa2a5e1548e6e74420"
integrity sha512-4IxSx4KlS9AughFvUOVC6d22y0fXtLpzDvlqxoPX+wf3ZCxtpg/dbVbitxU7Pcpj+hLIBm6xg2gAmK8asOMqjg==
"@expo/bunyan@^4.0.0":
version "4.0.0"
@@ -1377,14 +1377,15 @@
node-forge "^1.2.1"
nullthrows "^1.1.1"
"@expo/config-plugins@7.2.4", "@expo/config-plugins@~7.2.0":
version "7.2.4"
resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-7.2.4.tgz#c8d354348b746e53d70224f0bf7b87994f7c2936"
integrity sha512-TItGwmKH1GDjA5GlMkXo1A8pqeqppSK40aSVRVQaGZraUj+nuvtpWxNgEWZxWFumiatP2ocWwyWVjfmH+rJY6g==
"@expo/config-plugins@7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-7.8.4.tgz#533b5d536c1dc8b5544d64878b51bda28f2e1a1f"
integrity sha512-hv03HYxb/5kX8Gxv/BTI8TLc9L06WzqAfHRRXdbar4zkLcP2oTzvsLEF4/L/TIpD3rsnYa0KU42d0gWRxzPCJg==
dependencies:
"@expo/config-types" "^49.0.0-alpha.1"
"@expo/json-file" "~8.2.37"
"@expo/plist" "^0.0.20"
"@expo/config-types" "^50.0.0-alpha.1"
"@expo/fingerprint" "^0.6.0"
"@expo/json-file" "~8.3.0"
"@expo/plist" "^0.1.0"
"@expo/sdk-runtime-versions" "^1.0.0"
"@react-native/normalize-color" "^2.0.0"
chalk "^4.1.2"
@@ -1395,22 +1396,63 @@
resolve-from "^5.0.0"
semver "^7.5.3"
slash "^3.0.0"
slugify "^1.6.6"
xcode "^3.0.1"
xml2js "0.6.0"
"@expo/config-[email protected].0", "@expo/config-types@^49.0.0-alpha.1":
version "49.0.0"
resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-49.0.0.tgz#15ffef715285c06703f6fb7ec0cda853f645cc09"
integrity sha512-8eyREVi+K2acnMBe/rTIu1dOfyR2+AMnTLHlut+YpMV9OZPdeKV0Bs9BxAewGqBA2slslbQ9N39IS2CuTKpXkA==
"@expo/config-plugins@~7.8.0", "@expo/config-plugins@~7.8.2":
version "7.8.2"
resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-7.8.2.tgz#c00ce93c4d6c2cb9e345ed9cd56ceeea05ab8ddb"
integrity sha512-XM2eXA5EvcpmXFCui48+bVy8GTskYSjPf2yC+LliYv8PDcedu7+pdgmbnvH4eZCyHfTMO8/UiF+w8e5WgOEj5A==
dependencies:
"@expo/config-types" "^50.0.0-alpha.1"
"@expo/fingerprint" "^0.6.0"
"@expo/json-file" "~8.3.0"
"@expo/plist" "^0.1.0"
"@expo/sdk-runtime-versions" "^1.0.0"
"@react-native/normalize-color" "^2.0.0"
chalk "^4.1.2"
debug "^4.3.1"
find-up "~5.0.0"
getenv "^1.0.0"
glob "7.1.6"
resolve-from "^5.0.0"
semver "^7.5.3"
slash "^3.0.0"
slugify "^1.6.6"
xcode "^3.0.1"
xml2js "0.6.0"
"@expo/config@8.1.2", "@expo/config@~8.1.0":
version "8.1.2"
resolved "https://registry.yarnpkg.com/@expo/config/-/config-8.1.2.tgz#7fff28b3acefe39702e9f3ce1c9fd896a52caa80"
integrity sha512-4e7hzPj50mQIlsrzOH6XZ36O094mPfPTIDIH4yv49bWNMc7GFLTofB/lcT+QyxiLaJuC0Wlk9yOLB8DIqmtwug==
"@expo/config[email protected]", "@expo/config-types@^50.0.0", "@expo/config-types@^50.0.0-alpha.1":
version "50.0.0"
resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-50.0.0.tgz#b534d3ec997ec60f8af24f6ad56244c8afc71a0b"
integrity sha512-0kkhIwXRT6EdFDwn+zTg9R2MZIAEYGn1MVkyRohAd+C9cXOb5RA8WLQi7vuxKF9m1SMtNAUrf0pO+ENK0+/KSw==
"@expo/[email protected]":
version "8.5.4"
resolved "https://registry.yarnpkg.com/@expo/config/-/config-8.5.4.tgz#bb5eb06caa36e4e35dc8c7647fae63e147b830ca"
integrity sha512-ggOLJPHGzJSJHVBC1LzwXwR6qUn8Mw7hkc5zEKRIdhFRuIQ6s2FE4eOvP87LrNfDF7eZGa6tJQYsiHSmZKG+8Q==
dependencies:
"@babel/code-frame" "~7.10.4"
"@expo/config-plugins" "~7.2.0"
"@expo/config-types" "^49.0.0-alpha.1"
"@expo/config-plugins" "~7.8.2"
"@expo/config-types" "^50.0.0"
"@expo/json-file" "^8.2.37"
getenv "^1.0.0"
glob "7.1.6"
require-from-string "^2.0.2"
resolve-from "^5.0.0"
semver "7.5.3"
slugify "^1.3.4"
sucrase "3.34.0"
"@expo/config@~8.5.0":
version "8.5.2"
resolved "https://registry.yarnpkg.com/@expo/config/-/config-8.5.2.tgz#4a0de82279337a37b5f1f0958711fe56e8ea31c2"
integrity sha512-UYy9kWxjQAEDwlX7gwLk0+8IxGPcHJMLnYRYtR5C5xGIV+ML7tCA+qFz1p4gHZRPkJD+k7iZyqBtyqt8xm+zXw==
dependencies:
"@babel/code-frame" "~7.10.4"
"@expo/config-plugins" "~7.8.2"
"@expo/config-types" "^50.0.0"
"@expo/json-file" "^8.2.37"
getenv "^1.0.0"
glob "7.1.6"
@@ -1420,32 +1462,44 @@
slugify "^1.3.4"
sucrase "^3.20.0"
"@expo/[email protected].56":
version "1.0.56"
resolved "https://registry.yarnpkg.com/@expo/eas-build-job/-/eas-build-job-1.0.56.tgz#01f8782e3956a6782487f9b4da183b1a2fb95daa"
integrity sha512-OfPSvvcFIpt1SRnoxWMmUgHT7YuhZM10iYftBX4UqjgwjKIkmOpJUOgkmTd3cJMOaZRLP4MI4zsmk2gy9RCO9g==
"@expo/[email protected].78":
version "1.0.78"
resolved "https://registry.yarnpkg.com/@expo/eas-build-job/-/eas-build-job-1.0.78.tgz#d89aa0beb529f48120fd25b4b3ea4a897eff0033"
integrity sha512-Kio2p7NDAk9pi8Isi4D2CLdv/a0X4ybRImllzYWavC9NsPYA5TcRQ5S9odRNMSlrKmjUc+cBsF8rLYR8FUjjUw==
dependencies:
joi "^17.9.2"
joi "^17.11.0"
semver "^7.5.4"
"@expo/[email protected]":
version "0.3.22"
resolved "https://registry.yarnpkg.com/@expo/image-utils/-/image-utils-0.3.22.tgz#3a45fb2e268d20fcc761c87bca3aca7fd8e24260"
integrity sha512-uzq+RERAtkWypOFOLssFnXXqEqKjNj9eXN7e97d/EXUAojNcLDoXc0sL+F5B1I4qtlsnhX01kcpoIBBZD8wZNQ==
"@expo/fingerprint@^0.6.0":
version "0.6.0"
resolved "https://registry.yarnpkg.com/@expo/fingerprint/-/fingerprint-0.6.0.tgz#77366934673d4ecea37284109b4dd67f9e6a7487"
integrity sha512-KfpoVRTMwMNJ/Cf5o+Ou8M/Y0EGSTqK+rbi70M2Y0K2qgWNfMJ1gm6sYO9uc8lcTr7YSYM1Rme3dk7QXhpScNA==
dependencies:
"@expo/spawn-async" "^1.5.0"
chalk "^4.1.2"
debug "^4.3.4"
find-up "^5.0.0"
minimatch "^3.0.4"
p-limit "^3.1.0"
resolve-from "^5.0.0"
"@expo/image-utils@^0.4.0":
version "0.4.1"
resolved "https://registry.yarnpkg.com/@expo/image-utils/-/image-utils-0.4.1.tgz#78c54b8aaa974d0ac37fee5285683b54ff161b2c"
integrity sha512-EZb+VHSmw+a5s2hS9qksTcWylY0FDaIAVufcxoaRS9tHIXLjW5zcKW7Rhj9dSEbZbRVy9yXXdHKa3GQdUQIOFw==
dependencies:
"@expo/spawn-async" "1.5.0"
chalk "^4.0.0"
fs-extra "9.0.0"
getenv "^1.0.0"
jimp-compact "0.16.1"
mime "^2.4.4"
node-fetch "^2.6.0"
parse-png "^2.1.0"
resolve-from "^5.0.0"
semver "7.3.2"
tempy "0.3.0"
"@expo/[email protected]", "@expo/json-file@^8.2.37", "@expo/json-file@~8.2.37":
"@expo/[email protected]", "@expo/json-file@^8.2.37":
version "8.2.37"
resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-8.2.37.tgz#9c02d3b42134907c69cc0a027b18671b69344049"
integrity sha512-YaH6rVg11JoTS2P6LsW7ybS2CULjf40AbnAHw2F1eDPuheprNjARZMnyHFPkKv7GuxCy+B9GPcbOKgc4cgA80Q==
@@ -1454,10 +1508,19 @@
json5 "^2.2.2"
write-file-atomic "^2.3.0"
"@expo/[email protected]":
version "1.0.37"
resolved "https://registry.yarnpkg.com/@expo/logger/-/logger-1.0.37.tgz#79b2336d4e9ed70bd19a53168eb91d6a899f11d8"
integrity sha512-Xx3pt7FCsUkjsnu3lJoGp/LXYqoa5TyYx1/lgvfz4NSRgUT+5f6LNiYIowUjXab80PbW3gA/KqHYY9V7iZm8aQ==
"@expo/json-file@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-8.3.0.tgz#fc84af77b532a4e9bfb5beafd0e3b7f692b6bd7e"
integrity sha512-yROUeXJXR5goagB8c3muFLCzLmdGOvoPpR5yDNaXrnTp4euNykr9yW0wWhJx4YVRTNOPtGBnEbbJBW+a9q+S6g==
dependencies:
"@babel/code-frame" "~7.10.4"
json5 "^2.2.2"
write-file-atomic "^2.3.0"
"@expo/[email protected]":
version "1.0.57"
resolved "https://registry.yarnpkg.com/@expo/logger/-/logger-1.0.57.tgz#b64dfb29a06e8ca476905dd445a0e105fd919bcc"
integrity sha512-kd/1MOrVST9gQtnTD+qAV3KdrYCV9oShzIqYek+5XI3M/6QNvfv8IPr2pv+xaYZoCZgnNdI4ViWo0eYBDJMngA==
dependencies:
"@types/bunyan" "^1.8.8"
bunyan "^1.8.15"
@@ -1503,7 +1566,7 @@
dependencies:
node-forge "^1.2.1"
"@expo/[email protected]", "@expo/plist@^0.0.20":
"@expo/[email protected]":
version "0.0.20"
resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.0.20.tgz#a6b3124438031c02b762bad5a47b70584d3c0072"
integrity sha512-UXQ4LXCfTZ580LDHGJ5q62jSTwJFFJ1GqBu8duQMThiHKWbMJ+gajJh6rsB6EJ3aLUr9wcauxneL5LVRFxwBEA==
@@ -1512,6 +1575,15 @@
base64-js "^1.2.3"
xmlbuilder "^14.0.0"
"@expo/plist@^0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.1.0.tgz#eabc95f951d14e10c87fd0443ee01d567371f058"
integrity sha512-xWD+8vIFif0wKyuqe3fmnmnSouXYucciZXFzS0ZD5OV9eSAS1RGQI5FaGGJ6zxJ4mpdy/4QzbLdBjnYE5vxA0g==
dependencies:
"@xmldom/xmldom" "~0.7.7"
base64-js "^1.2.3"
xmlbuilder "^14.0.0"
"@expo/[email protected]":
version "5.1.23"
resolved "https://registry.yarnpkg.com/@expo/plugin-help/-/plugin-help-5.1.23.tgz#36d82111ec6c0e9870a3f0856ae7536186624912"
@@ -1533,15 +1605,15 @@
semver "^7.3.7"
tslib "^2.4.0"
"@expo/prebuild-config@6.2.5":
version "6.2.5"
resolved "https://registry.yarnpkg.com/@expo/prebuild-config/-/prebuild-config-6.2.5.tgz#2e7fdce8ddef3ac97fa05b4542f2b62a43bcea4b"
integrity sha512-XHgQ4OWZ03rzczD+D2ulQRjyHCVnA36cfX4q+r2x1Say4hI7lIg75ZQEsWdEMU9rZV8TbDUtZlPL4pxNWpYu7Q==
"@expo/prebuild-config@6.7.3":
version "6.7.3"
resolved "https://registry.yarnpkg.com/@expo/prebuild-config/-/prebuild-config-6.7.3.tgz#8444c1630bd92931c2d1a510791535b7282d8fa6"
integrity sha512-jZIHzlnvdg4Gnln06XR9tvirL3hSp/Jh48COhLKs51vb3THCWumUytZBS4DSMdvGwf8btnaB01Zg00xQhSDBsA==
dependencies:
"@expo/config" "~8.1.0"
"@expo/config-plugins" "~7.2.0"
"@expo/config-types" "^49.0.0-alpha.1"
"@expo/image-utils" "0.3.22"
"@expo/config" "~8.5.0"
"@expo/config-plugins" "~7.8.0"
"@expo/config-types" "^50.0.0-alpha.1"
"@expo/image-utils" "^0.4.0"
"@expo/json-file" "^8.2.37"
debug "^4.3.1"
fs-extra "^9.0.0"
@@ -1593,21 +1665,22 @@
dependencies:
cross-spawn "^7.0.3"
"@expo/[email protected].51":
version "1.0.51"
resolved "https://registry.yarnpkg.com/@expo/steps/-/steps-1.0.51.tgz#79aad4eb556e38a9f1c21703ebbea3af4f068807"
integrity sha512-S+2ESok2+kMjqWqJIK6p7Uk3aXf0hEbl7x10n1QBQdFzpkQmcNmpyNguOiFYyaj9dRleG2aPbwCv942m37VQWw==
"@expo/[email protected].81":
version "1.0.81"
resolved "https://registry.yarnpkg.com/@expo/steps/-/steps-1.0.81.tgz#1ff1707d28b5436b24d6d8dfd6037524e7e6b85d"
integrity sha512-1hQkZkNBH91L2aqz0HTf3uZYZ3KQGu1NeQboTuGNKhf8DNoT5RCcmymKsQoQ1AzmwVmduW2vaBkatqqEtnVamA==
dependencies:
"@expo/logger" "1.0.37"
"@expo/eas-build-job" "1.0.78"
"@expo/logger" "1.0.57"
"@expo/spawn-async" "^1.7.2"
arg "^5.0.2"
fs-extra "^11.1.1"
joi "^17.9.2"
fs-extra "^11.2.0"
joi "^17.11.0"
lodash.clonedeep "^4.5.0"
lodash.get "^4.4.2"
this-file "^2.0.3"
uuid "^9.0.0"
yaml "^2.3.1"
uuid "^9.0.1"
yaml "^2.3.4"
"@expo/[email protected]":
version "1.0.0"
@@ -2151,6 +2224,11 @@
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.1.0.tgz#6c9eafc78c1529248f8f4d92b0799a712b6052c6"
integrity sha512-i9YbZPN3QgfighY/1X1Pu118VUz2Fmmhd6b2n0/O8YVgGGfw0FbUYoA97k7FkpGJ+pLCFEDLUmAPPV4D1kpeFw==
"@hapi/hoek@^9.3.0":
version "9.3.0"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==
"@hapi/topo@^5.0.0":
version "5.0.0"
resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.0.0.tgz#c19af8577fa393a06e9c77b60995af959be721e7"
@@ -2158,6 +2236,13 @@
dependencies:
"@hapi/hoek" "^9.0.0"
"@hapi/topo@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012"
integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==
dependencies:
"@hapi/hoek" "^9.0.0"
"@humanwhocodes/config-array@^0.11.13":
version "0.11.14"
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b"
@@ -3399,6 +3484,13 @@
dependencies:
"@hapi/hoek" "^9.0.0"
"@sideway/address@^4.1.4":
version "4.1.4"
resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0"
integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==
dependencies:
"@hapi/hoek" "^9.0.0"
"@sideway/formula@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f"
@@ -6331,25 +6423,26 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
es5-ext@^0.10.35, es5-ext@^0.10.50:
version "0.10.53"
resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1"
integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==
es5-ext@^0.10.35, es5-ext@^0.10.50, es5-ext@^0.10.62, es5-ext@~0.10.14:
version "0.10.63"
resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.63.tgz#9c222a63b6a332ac80b1e373b426af723b895bd6"
integrity sha512-hUCZd2Byj/mNKjfP9jXrdVZ62B8KuA/VoK7X8nUh5qT+AxDmcbvZz041oDVZdbIN1qW6XY9VDNwzkvKnZvK2TQ==
dependencies:
es6-iterator "~2.0.3"
es6-symbol "~3.1.3"
next-tick "~1.0.0"
es6-iterator "^2.0.3"
es6-symbol "^3.1.3"
esniff "^2.0.1"
next-tick "^1.1.0"
es6-iterator@~2.0.3:
es6-iterator@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c=
integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==
dependencies:
d "1"
es5-ext "^0.10.35"
es6-symbol "^3.1.1"
es6-symbol@^3.1.1, es6-symbol@~3.1.3:
es6-symbol@^3.1.1, es6-symbol@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18"
integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==
@@ -6584,6 +6677,16 @@ [email protected]:
strip-ansi "^6.0.1"
text-table "^0.2.0"
esniff@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/esniff/-/esniff-2.0.1.tgz#a4d4b43a5c71c7ec51c51098c1d8a29081f9b308"
integrity sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==
dependencies:
d "^1.0.1"
es5-ext "^0.10.62"
event-emitter "^0.3.5"
type "^2.7.2"
espree@^9.6.0, espree@^9.6.1:
version "9.6.1"
resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f"
@@ -6632,6 +6735,14 @@ etag@~1.8.1:
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
event-emitter@^0.3.5:
version "0.3.5"
resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39"
integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==
dependencies:
d "1"
es5-ext "~0.10.14"
event-target-shim@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
@@ -7061,7 +7172,7 @@ fs-constants@^1.0.0:
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
[email protected]:
[email protected], fs-extra@^11.2.0:
version "11.2.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b"
integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==
@@ -8129,14 +8240,14 @@ invariant@^2.2.4:
loose-envify "^1.0.0"
ip@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
version "1.1.9"
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.9.tgz#8dfbcc99a754d07f425310b86a99546b1151e396"
integrity sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==
ip@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
version "2.0.1"
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105"
integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==
[email protected]:
version "1.9.1"
@@ -9192,14 +9303,14 @@ [email protected]:
"@sideway/formula" "^3.0.1"
"@sideway/pinpoint" "^2.0.0"
joi@^17.9.2:
version "17.9.2"
resolved "https://registry.yarnpkg.com/joi/-/joi-17.9.2.tgz#8b2e4724188369f55451aebd1d0b1d9482470690"
integrity sha512-Itk/r+V4Dx0V3c7RLFdRh12IOjySm2/WGPMubBT92cQvRfYZhPM2W0hZlctjj72iES8jsRCwp7S/cRmWBnJ4nw==
joi@^17.11.0:
version "17.12.0"
resolved "https://registry.yarnpkg.com/joi/-/joi-17.12.0.tgz#a3fb5715f198beb0471cd551dd26792089c308d5"
integrity sha512-HSLsmSmXz+PV9PYoi3p7cgIbj06WnEBNT28n+bbBNcPZXZFqCzzvGqpTBPujx/Z0nh1+KNQPDrNgdmQ8dq0qYw==
dependencies:
"@hapi/hoek" "^9.0.0"
"@hapi/topo" "^5.0.0"
"@sideway/address" "^4.1.3"
"@hapi/hoek" "^9.3.0"
"@hapi/topo" "^5.1.0"
"@sideway/address" "^4.1.4"
"@sideway/formula" "^3.0.1"
"@sideway/pinpoint" "^2.0.0"
@@ -10032,11 +10143,6 @@ [email protected]:
resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7"
integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==
mime@^2.4.4:
version "2.5.2"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe"
integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==
mimic-fn@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
@@ -10370,10 +10476,10 @@ neo-async@^2.6.2:
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
next-tick@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
integrity sha1-yobR/ogoFpsBICCOPchCS524NCw=
next-tick@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb"
integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==
nice-try@^1.0.4:
version "1.0.5"
@@ -12398,6 +12504,11 @@ slugify@^1.3.4:
resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.4.5.tgz#a7517acf5f4c02a4df41e735354b660a4ed1efcf"
integrity sha512-WpECLAgYaxHoEAJ8Q1Lo8HOs1ngn7LN7QjXgOLbmmfkcWvosyk4ZTXkTzKyhngK640USTZUlgoQJfED1kz5fnQ==
slugify@^1.6.6:
version "1.6.6"
resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.6.6.tgz#2d4ac0eacb47add6af9e04d3be79319cbcc7924b"
integrity sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==
smart-buffer@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz#91605c25d91652f4661ea69ccf45f1b331ca21ba"
@@ -12823,6 +12934,19 @@ [email protected]:
symbol-observable "^1.0.4"
ws "^5.2.0"
[email protected]:
version "3.34.0"
resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.34.0.tgz#1e0e2d8fcf07f8b9c3569067d92fbd8690fb576f"
integrity sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==
dependencies:
"@jridgewell/gen-mapping" "^0.3.2"
commander "^4.0.0"
glob "7.1.6"
lines-and-columns "^1.1.6"
mz "^2.7.0"
pirates "^4.0.1"
ts-interface-checker "^0.1.9"
sucrase@^3.20.0:
version "3.20.1"
resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.20.1.tgz#1c055e97d0fab2f9857f02461364075b3a4ab226"
@@ -13328,6 +13452,11 @@ type@^2.0.0:
resolved "https://registry.yarnpkg.com/type/-/type-2.1.0.tgz#9bdc22c648cf8cf86dd23d32336a41cfb6475e3f"
integrity sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==
type@^2.7.2:
version "2.7.2"
resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0"
integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==
typed-array-buffer@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60"
@@ -13601,7 +13730,7 @@ [email protected]:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.0.0.tgz#bc6ccf91b5ff0ac07bbcdbf1c7c4e150db4dbb6c"
integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==
[email protected]:
[email protected], uuid@^9.0.1:
version "9.0.1"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30"
integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==
@@ -14069,6 +14198,11 @@ yaml@^2.3.1:
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b"
integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==
yaml@^2.3.4:
version "2.3.4"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.4.tgz#53fc1d514be80aabf386dc6001eb29bf3b7523b2"
integrity sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==
[email protected], yargs-parser@^20.2.2:
version "20.2.4"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54"