Compare commits

..
95 Commits
Author SHA1 Message Date
Szymon Dziedzic b9064287fc v5.5.0 2023-10-25 12:00:01 +02:00
Szymon DziedzicandStanisław Chmiela 239ad4a88e [ENG-10384][eas-json] update eas.schema.json to include new JDK 17 image (#2099)
* [eas-json] update `eas.schema.json` to include new JDK 17 image

* Update packages/eas-json/schema/eas.schema.json

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

* update CHANGELOG.md

---------

Co-authored-by: Stanisław Chmiela <[email protected]>
2023-10-25 11:55:02 +02:00
dependabot[bot] 7374a93f03 Bump undici from 5.19.1 to 5.26.3 (#2088)
Bumps [undici](https://github.com/nodejs/undici) from 5.19.1 to 5.26.3.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v5.19.1...v5.26.3)

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

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-24 12:05:43 +02:00
dependabot[bot] b2bab3a523 Bump @babel/traverse from 7.12.5 to 7.23.2 (#2089)
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.12.5 to 7.23.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-24 12:02:52 +02:00
Szymon Dziedzic e8df9cdeb6 [eas-cli][eas-json] remove Intel resource class related code (#2093)
* [eas-cli][eas-json] remove Intel resource class related code

* fix types

* update CHANGELOG.md
2023-10-19 12:13:04 +02:00
Will Schurman 14980fe6e8 [expo-updates] Gate roll back to embedded to expo-updates >= 0.19.0 (#2094) 2023-10-18 15:39:01 -07:00
Josh McFarlin 743ae7c648 [eas-cli] VCS Context Fields to replace helper functions (#2086)
* [eas-cli] Add context fields for vcs clients

* [eas-cli] Replace vcs client helper with new context field

* [eas-cli] Pass instance of vcs client in helpers instead of re-calling vcs helper

* update CHANGELOG.md
2023-10-18 14:18:20 -07:00
Will Schurman 5ed155e67a [ci] Try to fix changelog-bot usage of hub CLI (#2095) 2023-10-18 12:05:11 -07:00
Radosław Krzemień aa14f21597 [eas-cli] [ENG-10334] Display device creation date (#2092)
* [eas-cli] Add createdAt to AppleDeviceFragment

Added a new field to gql type to fetch it later

See: https://linear.app/expo/issue/ENG-10334/show-creation-time-of-device-record-in-ad-hoc-device-selection-prompt

* [eas-cli] Generate gql schema

Generated a new graphql schema based on updated local version of www

See: https://linear.app/expo/issue/ENG-10334/show-creation-time-of-device-record-in-ad-hoc-device-selection-prompt

* [eas-cli] Fix mutation

Fixed mutation that started to fail after schema update

See: https://linear.app/expo/issue/ENG-10334/show-creation-time-of-device-record-in-ad-hoc-device-selection-prompt

* [eas-cli] Display creation date

Added creation date to the AppleDevice formatting function used to display details in cli

See: https://linear.app/expo/issue/ENG-10334/show-creation-time-of-device-record-in-ad-hoc-device-selection-prompt

* [eas-cli] Add changelog

Manually added the changelog entry since the automation failed for some reason

See: https://linear.app/expo/issue/ENG-10334/show-creation-time-of-device-record-in-ad-hoc-device-selection-prompt
2023-10-18 17:52:04 +02:00
Will Schurman 91787e1f76 [eas-update] Increase asset upload timeout to 90s and reset on upload retry for slow connections (#2085) 2023-10-16 10:30:28 -07:00
Radoslaw Krzemien 474c95a7b7 Revert "[eas-cli] Add createdAt to AppleDeviceFragment"
This reverts commit 1948fd6e81.
2023-10-16 16:03:49 +02:00
Radoslaw Krzemien 0e4f00df2f Revert "[eas-cli] Generate gql schema"
This reverts commit 8df2a08b20.
2023-10-16 16:03:36 +02:00
Radoslaw Krzemien c5d75568ef Revert "[eas-cli] Fix mutation"
This reverts commit 606ce9a1ff.
2023-10-16 16:03:25 +02:00
Radoslaw Krzemien 4982e12bf6 Revert "[eas-cli] Display creation date"
This reverts commit 41c039c428.
2023-10-16 16:03:09 +02:00
Radoslaw Krzemien 41c039c428 [eas-cli] Display creation date
Added creation date to the AppleDevice formatting function used to display details in cli

See: https://linear.app/expo/issue/ENG-10334/show-creation-time-of-device-record-in-ad-hoc-device-selection-prompt
2023-10-16 15:31:07 +02:00
Radoslaw Krzemien 606ce9a1ff [eas-cli] Fix mutation
Fixed mutation that started to fail after schema update

See: https://linear.app/expo/issue/ENG-10334/show-creation-time-of-device-record-in-ad-hoc-device-selection-prompt
2023-10-16 15:30:19 +02:00
Radoslaw Krzemien 8df2a08b20 [eas-cli] Generate gql schema
Generated a new graphql schema based on updated local version of www

See: https://linear.app/expo/issue/ENG-10334/show-creation-time-of-device-record-in-ad-hoc-device-selection-prompt
2023-10-16 15:29:27 +02:00
Radoslaw Krzemien 1948fd6e81 [eas-cli] Add createdAt to AppleDeviceFragment
Added a new field to gql type to fetch it later

See: https://linear.app/expo/issue/ENG-10334/show-creation-time-of-device-record-in-ad-hoc-device-selection-prompt
2023-10-16 15:21:33 +02:00
Alan Hughes 49b6e1f9e4 [eas-cli] add account type to project owner prompt (#2083) 2023-10-11 09:56:27 +01:00
dependabot[bot] a56abe33dd Bump graphql from 16.6.0 to 16.8.1 (#2060)
Bumps [graphql](https://github.com/graphql/graphql-js) from 16.6.0 to 16.8.1.
- [Release notes](https://github.com/graphql/graphql-js/releases)
- [Commits](https://github.com/graphql/graphql-js/compare/v16.6.0...v16.8.1)

---
updated-dependencies:
- dependency-name: graphql
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-03 11:13:56 -07:00
Kadi Kraman feaedbe634 [eas-cli] [ENG-10225] add requiredPackageManager to build metadata (#2067)
* Add requiredPackageManager to build metadata

* Use correct version in changelog

* Fix changelog

* Update @expo/eas-build-job library

* Update graphql schema

* Update gql schema
2023-10-03 11:28:38 +01:00
Expo CI 0fba735f7a update CHANGELOG.md 2023-09-28 22:12:53 +00:00
Brent Vatne 480bc30468 v5.4.0 2023-09-28 15:01:57 -07:00
Jakov Glavina c1c9e06f76 feat: add tap to pay on iphone entitlement (#2069) 2023-09-28 14:44:06 -07:00
Expo CI 5fb68a652b update CHANGELOG.md 2023-09-28 19:31:07 +00:00
Brent Vatne 056d0b1017 v5.3.1 2023-09-28 12:22:45 -07:00
Szymon Dziedzic cc99794bbd [ENG-10176][eas-json] update images info in eas.schema.json (#2068) 2023-09-28 11:59:43 -07:00
Expo CI 04049a8d1f update CHANGELOG.md 2023-09-25 16:41:24 +00:00
Szymon Dziedzic 5bdd46a2a9 v5.3.0 2023-09-25 18:27:59 +02:00
Szymon Dziedzic a7e88bd7cb upgrade eas-cli-local-build-plugin to 1.0.44 2023-09-25 18:27:06 +02:00
Kadi KramanandSzymon Dziedzic 78b75c6224 [eas-cli] [eas-json] [ENG-10069] add support for bun (#2055)
* Update eas-build-job dependency

* Add bun to eas-cli

* Add bun to eas-json

* Add changelog

* Use correct PR in changelog

* Update packages/eas-json/schema/eas.schema.json

Co-authored-by: Szymon Dziedzic <[email protected]>

* Update gql schema

---------

Co-authored-by: Szymon Dziedzic <[email protected]>
2023-09-25 16:54:23 +01:00
Szymon Dziedzic 52f54fc7ae fix tests 2023-09-18 10:26:36 +02:00
Piotr Szeremeta 7ddd630cfd [FIX] Remove semver validation from node version read from .nvmrc (#2052)
* [FIX] Remove semver validation from node version read from .nvmrc

Node version can be specified as an alias (such as `iojs`, `lts/hydrogen` etc), so validating it as semver may cause errors for some users.

* update CHANGELOG.md
2023-09-18 08:28:39 +02:00
_nderscore 8751a2835f feat(eas-cli): expose expo export dev flag as an option in eas update (#2050) 2023-09-13 13:00:01 -07:00
Piotr Szeremeta da9829a853 [ENG-5266] Suggest correct bundleId when account name not available (#2027) 2023-09-11 14:56:53 +02:00
Quinlan Jung cc822b18f3 [eas-cli] rollouts: more robust printing function (#2047)
* [eas-cli] rollouts: more robust printing function

* update CHANGELOG.md
2023-09-06 11:10:44 -07:00
Expo CI bcab3bcb09 update CHANGELOG.md 2023-09-05 20:58:51 +00:00
Quinlan Jung a5dc0bd27c v5.2.0 2023-09-05 13:50:41 -07:00
Quinlan Jung 54127c4e37 [ENG-9828][eas-cli] rollouts: view action for CI (#2040)
* [eas-cli] rollouts: non-interactive view

* update CHANGELOG.md

* rebase
2023-09-05 13:49:12 -07:00
Quinlan Jung 9097ab2537 [ENG-9602][eas-cli] rollouts: json output for ci (#2037)
* [eas-cli] rollouts: json output for ci

* update CHANGELOG.md

* fix tests
2023-09-05 13:01:20 -07:00
Quinlan Jung 4e2029a5c5 [eas-cli] rollout tests (#2042)
* [eas-cli] rollout tests

* update CHANGELOG.md
2023-09-05 12:30:31 -07:00
Quinlan Jung ad02a056d7 [eas-cli] remove unreachable codesigning option (#2041)
* [eas-cli] remove unreachable option

* update CHANGELOG.md
2023-09-05 12:29:23 -07:00
Quinlan Jung ea9f734b11 [eas-cli] fix graphql (#2039)
* [eas-cli] fix graphql

* update CHANGELOG.md
2023-09-05 12:27:54 -07:00
Piotr Szeremeta 7db9d79c55 [Fix] Remove doubled definition of pnpm field from eas.schema.json (#2038) 2023-09-04 07:44:39 +02:00
Quinlan Jung 2e31b42b76 [eas-cli] only print channel-branch pairing if we created a channel (#2036)
* [eas-cli] only print channel-branch pairing if we created a channel

* update CHANGELOG.md
2023-09-01 12:38:42 -07:00
Expo CI 66d02d9724 update CHANGELOG.md 2023-09-01 14:14:32 +00:00
Piotr Szeremeta 7c96cc10cf v5.1.0 2023-09-01 16:05:53 +02:00
Piotr Szeremeta 523a781ba5 upgrade eas-cli-local-build-plugin to 1.0.42 2023-09-01 16:05:39 +02:00
Piotr Szeremeta 6cf8bd5c5a [ENG-9473] Support installing selected pnpm version (#1988)
* [wip][ENG-9473]

* [ENG-9473] Add `pnpm` option to `builderEnvironment`.

* update CHANGELOG.md

* Fix changelog
2023-09-01 15:26:28 +02:00
dependabot[bot] 67e9ea706b Bump word-wrap from 1.2.3 to 1.2.5 (#2033)
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.5.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.5)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-30 17:04:07 +02:00
Szymon Dziedzic c22f410889 [eas-cli][eas-json] bump semver version (#2030)
* [eas-cli][eas-json] bump `semver` version

* update scripts yarn.lock
2023-08-30 16:00:49 +02:00
Radosław Krzemień 9ff47af4fa [eas-cli] [ENG-7536] Stop app config error repeating (#2020)
* [eas-cli] Stop app config error repeating

If app config error is thrown it is re-thrown with modified message instead of printing it to the as a "cryptic error" and repeating with 0% chances of success (since the config is incorrect)

See: https://linear.app/expo/issue/ENG-7536/make-app-config-error-on-credentials-command-not-repeat-indefinitely

* [eas-cli] Create custom error

Replaced generic error with specific message with a custom error class, which allows for not relying on a message to be exactly as expected

See: https://linear.app/expo/issue/ENG-7536/make-app-config-error-on-credentials-command-not-repeat-indefinitely

* update CHANGELOG.md

* [eas-cli] Remove blank line

Removed blank line from changelog

See: https://linear.app/expo/issue/ENG-7536/make-app-config-error-on-credentials-command-not-repeat-indefinitely
2023-08-30 09:11:00 +02:00
Quinlan Jung 324dce8fc0 [eas-cli] fix printing bug: branch with no update (#2023)
* [eas-cli] fix branch with no update printing bug

* tests

* update CHANGELOG.md
2023-08-29 14:07:35 -07:00
Expo CI b30c86f0c0 update CHANGELOG.md 2023-08-29 11:51:19 +00:00
Szymon Dziedzic 008279e1dd v5.0.2 2023-08-29 13:15:39 +02:00
Cedric van Putten d00814f84b fix(eas-cli): implement variadic --platform flag when creating EAS updates (#1939)
* fix(eas-cli): implement variadic `--platform` flag when creating EAS updates

* fix(eas-cli): finish todo and set minimum `@expo/[email protected]` version for multiple `--platform` flags during export

* update CHANGELOG.md

* fix(eas-cli): be verbose about `--platform=<flag>` in bundle script
2023-08-29 13:11:49 +02:00
Expo CI 81aa127e28 update CHANGELOG.md 2023-08-28 19:05:12 +00:00
Szymon Dziedzic d321a0bccb v5.0.1 2023-08-28 20:54:10 +02:00
Szymon Dziedzic a1d86549ed [eas-cli] fix eas update passing platform argument incorrectly to expo-cli (#2028)
* [eas-cli] fix `eas update` passing `platform` argument incorrectly to `expo-cli`

* update CHANGELOG.md
2023-08-28 20:51:18 +02:00
Expo CI f7e9af913c update CHANGELOG.md 2023-08-28 14:00:12 +00:00
Szymon Dziedzic 137f9d4ac7 v5.0.0 2023-08-28 14:20:36 +02:00
Szymon Dziedzic 2ac863a9e3 upgrade eas-cli-local-build-plugin to 1.0.39 2023-08-28 14:19:20 +02:00
Quinlan Jung 11be9eba49 [ENG-9685][eas-cli] create a linked channel on build if not exists (#2017)
* [eas-cli] create linked channel on build

* refactor

* update CHANGELOG.md

* amend doc block
2023-08-25 12:07:59 -07:00
Will Schurman b36db15601 [eas-cli][updates] configure updates as well when somebody tries to run a build with channel set (#2016) 2023-08-25 09:14:29 -07:00
Piotr Szeremeta 93c5dc1a32 [ENG-9422] nvmrc support for setting node version (#1998)
* [ENG-9422][eas-cli] Use .nvmrc to set node version

* update CHANGELOG.md
2023-08-25 15:46:55 +02:00
Szymon Dziedzic c86550c0c8 [eas-cli][eas-json] add developmentClient to metadata (#2015)
* [eas-cli][eas-json] add `developmentClient` to metadata

* update CHANGELOG.md
2023-08-25 13:26:33 +02:00
Brent Vatne 36b4296d3c [.github] Add issue template config 2023-08-24 17:09:47 -07:00
Brent Vatne 8c08541ca3 Create SECURITY.md 2023-08-24 17:06:03 -07:00
Will Schurman 5a1406d39c [eas-cli] Add info to EAS Update asset upload process about asset counts and limits (#2013) 2023-08-24 09:22:30 -07:00
Radosław Krzemień 78ea88cc5f [eas-cli] [ENG-7591] Detect not provisioned devices (#2011)
* [eas-cli] Detect not provisioned devices

After selecting devices to be provisioned and making a call to App Store Connect API the result is compared with the list of chosen devices. If any are missing, a message is displayed to the user

See: https://linear.app/expo/issue/ENG-7591/detect-processing-devices-on-apple-developer-portal-and-dont-allow-the

* [eas-cli] Adjust message

Updated the message with the link to the devices page in the Apple Developer portal

See: https://linear.app/expo/issue/ENG-7591/detect-processing-devices-on-apple-developer-portal-and-dont-allow-the

* update CHANGELOG.md
2023-08-24 15:35:48 +02:00
Will Schurman 6cb02d0ccd [eas-cli][eas-update] Support republishing roll back to embedded updates (#2006) 2023-08-15 11:39:24 -04:00
Will Schurman d6c7623718 [eas-cli][eas-update] Add rollback disambiguation command (#2004) 2023-08-15 11:36:18 -04:00
Quinlan Jung 32142b4fe8 [eas-cli] more branch mapping utils (#2003)
* [eas-cli] more branch mapping utils

* update CHANGELOG.md
2023-08-14 14:51:29 -07:00
Will Schurman 6bdee0f395 [eas-cli][update] Only export at most ios and android dist (#2002) 2023-08-14 17:28:06 -04:00
Quinlan Jung baf94a21c3 [eas-cli] more branch map utility functions (#2001)
* [eas-cli] more branch map utility functions

* update CHANGELOG.md

* feedback
2023-08-11 11:35:47 -07:00
Radoslaw Krzemien 162d64bce6 Revert "[eas-cli] Update oclif version"
This reverts commit d16c1fc757.
2023-08-11 12:22:56 +02:00
Radoslaw Krzemien d16c1fc757 [eas-cli] Update oclif version
Updated oclif version

See: https://linear.app/expo/issue/ENG-9175/update-oclif-in-eas-cli
2023-08-11 12:22:17 +02:00
Expo CI e42ea7e2ec update CHANGELOG.md 2023-08-10 10:26:10 +00:00
Szymon Dziedzic 5fea1ad16e v4.1.2 2023-08-10 12:12:49 +02:00
Szymon Dziedzic 2a57a2eb3d upgrade eas-cli-local-build-plugin to 1.0.38 2023-08-10 12:12:41 +02:00
Quinlan Jung 5628b78523 [eas-cli] make branch mapping utility files have no dependencies (#1993)
* [eas-cli] generalize branch mapping utils

* make standalone

* update CHANGELOG.md
2023-08-09 15:32:19 -07:00
Expo CI 19d1e6bffd update CHANGELOG.md 2023-08-08 18:36:49 +00:00
Quinlan Jung 88b068511c v4.1.1 2023-08-08 11:28:16 -07:00
Quinlan Jung 842efcf3ab upgrade eas-cli-local-build-plugin to 1.0.35 2023-08-08 11:28:02 -07:00
Quinlan Jung f5f08aa506 [eas-cli] rollouts websupport (#1997)
* [eas-cli] rollouts websupport

* update CHANGELOG.md

* fix changelog
2023-08-08 11:26:18 -07:00
Expo CI 9f7f412cfb update CHANGELOG.md 2023-08-08 13:19:03 +00:00
Szymon Dziedzic e369ec1e25 v4.1.0 2023-08-08 15:10:39 +02:00
Szymon Dziedzic b353441f31 upgrade eas-cli-local-build-plugin to 1.0.34 2023-08-08 15:10:24 +02:00
Szymon Dziedzic 4db35e73c6 [eas-cli] bump @expo/steps version (#1995) 2023-08-08 15:02:33 +02:00
Szymon Dziedzic 10bc872dc9 [eas-json][eas-cli] add global withoutCredentials property to eas.json (#1994)
* [eas-json][eas-cli] add global `withoutCredentials` property to `eas.json`

* update CHANGELOG.md

* fix tests
2023-08-08 14:13:25 +02:00
Szymon Dziedzic fedc39ea48 [eas-cli] pass iOS credentials to custom builds (#1989)
* [eas-cli] pass iOS credentials to custom builds

* update CHANGELOG.md
2023-08-08 13:55:18 +02:00
Expo CI 6046723769 update CHANGELOG.md 2023-08-08 08:39:19 +00:00
Quinlan Jung afaee9df38 v4.0.1 2023-08-07 16:28:14 -07:00
Quinlan Jung de39d6f00d [eas-cli] account for empty branch mapping (#1992)
* [eas-cli] account for empty branch mapping

* update CHANGELOG.md
2023-08-07 16:24:32 -07:00
Expo CI 401751fffa update CHANGELOG.md 2023-08-07 20:40:01 +00:00
146 changed files with 4975 additions and 1287 deletions

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Expo Developers Discord
url: https://chat.expo.dev/
about: Join other developers in discussions regarding Expo and EAS.
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
with:
node-version: 18
- name: Checkout Pull Request
run: hub pr checkout ${{ github.event.issue.number }}
run: gh pr checkout ${{ github.event.issue.number }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install dependencies
+138
View File
@@ -6,6 +6,144 @@ This is the log of notable changes to EAS CLI and related packages.
### 🛠 Breaking changes
### 🎉 New features
- Add account type to the items in the prompt to select project owner. ([#2083](https://github.com/expo/eas-cli/pull/2083) by [@alanjhughes](https://github.com/alanjhughes))
- Gate roll back to embedded to expo-updates >= 0.19.0. ([#2094](https://github.com/expo/eas-cli/pull/2094) by [@wschurman](https://github.com/wschurman))
### 🐛 Bug fixes
- EAS Update: Increase asset upload timeout to 90s and reset on upload retry for slow connections. ([#2085](https://github.com/expo/eas-cli/pull/2085) by [@wschurman](https://github.com/wschurman))
### 🧹 Chores
- Add `requiredPackageManager` to metadata. ([#2067](https://github.com/expo/eas-cli/pull/2067) by [@kadikraman](https://github.com/kadikraman))
- Move `getVcsClient` into command context. ([#2086](https://github.com/expo/eas-cli/pull/2086) by [@Josh-McFarlin](https://github.com/Josh-McFarlin))
- Display Apple device creation date when listing devices. ([#2092](https://github.com/expo/eas-cli/pull/2092) by [@radoslawkrzemien](https://github.com/radoslawkrzemien))
- Clean up Intel resource classes code after their deletion. ([#2093](https://github.com/expo/eas-cli/pull/2093) by [@szdziedzic](https://github.com/szdziedzic))
- Update images descriptions in `eas.schema.json` and add info about the new JDK 17 image. ([#2099](https://github.com/expo/eas-cli/pull/2099) by [@szdziedzic](https://github.com/szdziedzic))
## [5.4.0](https://github.com/expo/eas-cli/releases/tag/v5.4.0) - 2023-09-28
### 🎉 New features
- Add support for the Tap to Pay on iPhone iOS entitlement. ([#2069](https://github.com/expo/eas-cli/pull/2069) by [@fobos531](https://github.com/fobos531))
## [5.3.1](https://github.com/expo/eas-cli/releases/tag/v5.3.1) - 2023-09-28
### 🧹 Chores
- Update EAS Build images description in our VSCode plugin. Add new `macos-ventura-13.6-xcode-15.0` image. ([#2068](https://github.com/expo/eas-cli/pull/2068) by [@szdziedzic](https://github.com/szdziedzic))
## [5.3.0](https://github.com/expo/eas-cli/releases/tag/v5.3.0) - 2023-09-25
### 🎉 New features
- Update: expose expo cli `--dev` flag as an argument. ([#2050](https://github.com/expo/eas-cli/pull/2050) by [@nderscore](https://github.com/nderscore))
- Support `bun` option in eas.json. ([#2055](https://github.com/expo/eas-cli/pull/2055) by [@kadikraman](https://github.com/kadikraman))
### 🐛 Bug fixes
- Support node aliases in .nvmrc. ([#2052](https://github.com/expo/eas-cli/pull/2052) by [@khamilowicz](https://github.com/khamilowicz))
### 🧹 Chores
- Rollouts: more robust printing function. ([#2047](https://github.com/expo/eas-cli/pull/2047) by [@quinlanj](https://github.com/quinlanj))
## [5.2.0](https://github.com/expo/eas-cli/releases/tag/v5.2.0) - 2023-09-05
### 🎉 New features
- Rollouts: json output for ci. ([#2037](https://github.com/expo/eas-cli/pull/2037) by [@quinlanj](https://github.com/quinlanj))
### 🐛 Bug fixes
- Update: only print channel-branch pairing if we created a channel. ([#2036](https://github.com/expo/eas-cli/pull/2036) by [@quinlanj](https://github.com/quinlanj))
### 🧹 Chores
- Added rollout tests. ([#2042](https://github.com/expo/eas-cli/pull/2042) by [@quinlanj](https://github.com/quinlanj))
- Remove unreachable codesigning option. ([#2041](https://github.com/expo/eas-cli/pull/2041) by [@quinlanj](https://github.com/quinlanj))
- Fix generated graphql tsc errors. ([#2039](https://github.com/expo/eas-cli/pull/2039) by [@quinlanj](https://github.com/quinlanj))
- Rollouts: view action for CI. ([#2040](https://github.com/expo/eas-cli/pull/2040) by [@quinlanj](https://github.com/quinlanj))
## [5.1.0](https://github.com/expo/eas-cli/releases/tag/v5.1.0) - 2023-09-01
### 🎉 New features
- Support `pnpm` option in eas.json. ([#1988](https://github.com/expo/eas-cli/pull/1988) by [@khamilowicz](https://github.com/khamilowicz))
### 🐛 Bug fixes
- Make app config error not repeat indefinitely. ([#2020](https://github.com/expo/eas-cli/pull/2020) by [@radoslawkrzemien](https://github.com/radoslawkrzemien))
## [5.0.2](https://github.com/expo/eas-cli/releases/tag/v5.0.2) - 2023-08-29
### 🐛 Bug fixes
- Add proper expo cli `--platform` flag handling when exporting updates. ([#1939](https://github.com/expo/eas-cli/pull/1939) by [@byCedric](https://github.com/byCedric))
## [5.0.1](https://github.com/expo/eas-cli/releases/tag/v5.0.1) - 2023-08-28
### 🐛 Bug fixes
- Pass `platform` argument to expo-cli correctly when using the `eas update` command. ([#2028](https://github.com/expo/eas-cli/pull/2028) by [@szdziedzic](https://github.com/szdziedzic))
## [5.0.0](https://github.com/expo/eas-cli/releases/tag/v5.0.0) - 2023-08-28
### 🛠 Breaking changes
- Only export at most ios and android dist for EAS updates. ([#2002](https://github.com/expo/eas-cli/pull/2002) by [@wschurman](https://github.com/wschurman))
### 🎉 New features
- Add rollback disambiguation command. ([#2004](https://github.com/expo/eas-cli/pull/2004) by [@wschurman](https://github.com/wschurman))
- Detect devices that fail to be provisioned, list them to the user and show the explanation message with the link to the devices page to check actual status. ([#2011](https://github.com/expo/eas-cli/pull/2011) by [@radoslawkrzemien](https://github.com/radoslawkrzemien))
- Add info to EAS Update asset upload process about asset counts and limits. ([#2013](https://github.com/expo/eas-cli/pull/2013) by [@wschurman](https://github.com/wschurman))
- .nvmrc support for setting node version. ([#1954](https://github.com/expo/eas-cli/pull/1954) by [@khamilowicz](https://github.com/khamilowicz))
### 🐛 Bug fixes
- Support republishing roll back to embedded updates. ([#2006](https://github.com/expo/eas-cli/pull/2006) by [@wschurman](https://github.com/wschurman))
- Configure updates as well when somebody tries to run a build with channel set. ([#2016](https://github.com/expo/eas-cli/pull/2016) by [@wschurman](https://github.com/wschurman))
- Fix printing bug: branch with no update. ([#2023](https://github.com/expo/eas-cli/pull/2023) by [@quinlanj](https://github.com/quinlanj))
### 🧹 Chores
- More branch map utility functions. ([#2001](https://github.com/expo/eas-cli/pull/2001) by [@quinlanj](https://github.com/quinlanj))
- More branch mapping utils. ([#2003](https://github.com/expo/eas-cli/pull/2003) by [@quinlanj](https://github.com/quinlanj))
- Create a linked channel on build if not exists. ([#2017](https://github.com/expo/eas-cli/pull/2017) by [@quinlanj](https://github.com/quinlanj))
- Add `developmentClient` to metadata. ([#2015](https://github.com/expo/eas-cli/pull/2015) by [@szdziedzic](https://github.com/szdziedzic))
## [4.1.2](https://github.com/expo/eas-cli/releases/tag/v4.1.2) - 2023-08-10
### 🧹 Chores
- Make branch mapping utility files have no dependencies. ([#1993](https://github.com/expo/eas-cli/pull/1993) by [@quinlanj](https://github.com/quinlanj))
## [4.1.1](https://github.com/expo/eas-cli/releases/tag/v4.1.1) - 2023-08-08
### 🧹 Chores
- Logger to say website support is coming soon for rollouts. ([#1997](https://github.com/expo/eas-cli/pull/1997) by [@quinlanj](https://github.com/quinlanj))
## [4.1.0](https://github.com/expo/eas-cli/releases/tag/v4.1.0) - 2023-08-08
### 🎉 New features
- Pass credentials to custom iOS builds. ([#1989](https://github.com/expo/eas-cli/pull/1989) by [@szdziedzic](https://github.com/szdziedzic))
- Add the `withoutCredentials` option as a common build profile field in `eas.json`. ([#1994](https://github.com/expo/eas-cli/pull/1994) by [@szdziedzic](https://github.com/szdziedzic))
## [4.0.1](https://github.com/expo/eas-cli/releases/tag/v4.0.1) - 2023-08-08
### 🐛 Bug fixes
- Fix `eas channel:*` to work with empty branch mappings. ([#1992](https://github.com/expo/eas-cli/pull/1992) by [@quinlanj](https://github.com/quinlanj))
## [4.0.0](https://github.com/expo/eas-cli/releases/tag/v4.0.0) - 2023-08-07
### 🛠 Breaking changes
- Release redesigned `eas channel:rollout` into developer preview. The set of flag arguments are different, in addition to the workflow. ([#1986](https://github.com/expo/eas-cli/pull/1986) by [@quinlanj](https://github.com/quinlanj))
### 🎉 New features
+5
View File
@@ -0,0 +1,5 @@
# Security Policy
## Reporting a Vulnerability
Instead of opening a GitHub issue for security vulnerabilities, send an email to our secure inbox: secure@expo.io.
+1 -1
View File
@@ -1,6 +1,6 @@
{
"npmClient": "yarn",
"useWorkspaces": true,
"version": "4.0.0",
"version": "5.5.0",
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
}
+108 -59
View File
@@ -110,6 +110,8 @@ eas --help COMMAND
* [`eas update:delete GROUPID`](#eas-updatedelete-groupid)
* [`eas update:list`](#eas-updatelist)
* [`eas update:republish`](#eas-updaterepublish)
* [`eas update:roll-back-to-embedded`](#eas-updateroll-back-to-embedded)
* [`eas update:rollback`](#eas-updaterollback)
* [`eas update:view GROUPID`](#eas-updateview-groupid)
* [`eas webhook:create`](#eas-webhookcreate)
* [`eas webhook:delete [ID]`](#eas-webhookdelete-id)
@@ -133,7 +135,7 @@ ALIASES
$ eas login
```
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/account/login.ts)_
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/account/login.ts)_
## `eas account:logout`
@@ -150,7 +152,7 @@ ALIASES
$ eas logout
```
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/account/logout.ts)_
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/account/logout.ts)_
## `eas account:view`
@@ -167,7 +169,7 @@ ALIASES
$ eas whoami
```
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/account/view.ts)_
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/account/view.ts)_
## `eas analytics [STATUS]`
@@ -181,7 +183,7 @@ DESCRIPTION
display or change analytics settings
```
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/analytics.ts)_
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/analytics.ts)_
## `eas autocomplete [SHELL]`
@@ -231,7 +233,7 @@ DESCRIPTION
create a branch
```
_See code: [src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/branch/create.ts)_
_See code: [src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/branch/create.ts)_
## `eas branch:delete [NAME]`
@@ -252,7 +254,7 @@ DESCRIPTION
delete a branch
```
_See code: [src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/branch/delete.ts)_
_See code: [src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/branch/delete.ts)_
## `eas branch:list`
@@ -272,7 +274,7 @@ DESCRIPTION
list all branches
```
_See code: [src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/branch/list.ts)_
_See code: [src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/branch/list.ts)_
## `eas branch:rename`
@@ -292,7 +294,7 @@ DESCRIPTION
rename a branch
```
_See code: [src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/branch/rename.ts)_
_See code: [src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/branch/rename.ts)_
## `eas branch:view [NAME]`
@@ -315,7 +317,7 @@ DESCRIPTION
view a branch
```
_See code: [src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/branch/view.ts)_
_See code: [src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/branch/view.ts)_
## `eas build`
@@ -345,7 +347,7 @@ DESCRIPTION
start a build
```
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/build/index.ts)_
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/build/index.ts)_
## `eas build:cancel [BUILD_ID]`
@@ -362,7 +364,7 @@ DESCRIPTION
cancel a build
```
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/build/cancel.ts)_
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/build/cancel.ts)_
## `eas build:configure`
@@ -379,7 +381,7 @@ DESCRIPTION
configure the project to support EAS Build
```
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/build/configure.ts)_
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/build/configure.ts)_
## `eas build:inspect`
@@ -414,7 +416,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/v4.0.0/packages/eas-cli/src/commands/build/inspect.ts)_
_See code: [src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/build/inspect.ts)_
## `eas build:list`
@@ -452,7 +454,7 @@ DESCRIPTION
list all builds for your project
```
_See code: [src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/build/list.ts)_
_See code: [src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/build/list.ts)_
## `eas build:resign`
@@ -478,7 +480,7 @@ DESCRIPTION
re-sign a build archive
```
_See code: [src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/build/resign.ts)_
_See code: [src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/build/resign.ts)_
## `eas build:run`
@@ -502,7 +504,7 @@ DESCRIPTION
run simulator/emulator builds from eas-cli
```
_See code: [src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/build/run.ts)_
_See code: [src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/build/run.ts)_
## `eas build:submit`
@@ -551,7 +553,7 @@ DESCRIPTION
get the latest version from EAS servers
```
_See code: [src/commands/build/version/get.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/build/version/get.ts)_
_See code: [src/commands/build/version/get.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/build/version/get.ts)_
## `eas build:version:set`
@@ -570,7 +572,7 @@ DESCRIPTION
update version of an app
```
_See code: [src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/build/version/set.ts)_
_See code: [src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/build/version/set.ts)_
## `eas build:version:sync`
@@ -589,7 +591,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/v4.0.0/packages/eas-cli/src/commands/build/version/sync.ts)_
_See code: [src/commands/build/version/sync.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/build/version/sync.ts)_
## `eas build:view [BUILD_ID]`
@@ -606,7 +608,7 @@ DESCRIPTION
view a build for your project
```
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/build/view.ts)_
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/build/view.ts)_
## `eas channel:create [NAME]`
@@ -627,7 +629,7 @@ DESCRIPTION
create a channel
```
_See code: [src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/channel/create.ts)_
_See code: [src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/channel/create.ts)_
## `eas channel:edit [NAME]`
@@ -649,7 +651,7 @@ DESCRIPTION
point a channel at a new branch
```
_See code: [src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/channel/edit.ts)_
_See code: [src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/channel/edit.ts)_
## `eas channel:list`
@@ -669,7 +671,7 @@ DESCRIPTION
list all channels
```
_See code: [src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/channel/list.ts)_
_See code: [src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/channel/list.ts)_
## `eas channel:rollout [CHANNEL]`
@@ -677,7 +679,7 @@ Roll a new branch out on a channel incrementally.
```
USAGE
$ eas channel:rollout [CHANNEL] [--action create|edit|end] [--percent <value>] [--outcome
$ eas channel:rollout [CHANNEL] [--action create|edit|end|view] [--percent <value>] [--outcome
republish-and-revert|revert] [--branch <value>] [--runtime-version <value>] [--private-key-path <value>] [--json
--non-interactive]
@@ -685,7 +687,7 @@ ARGUMENTS
CHANNEL channel on which the rollout should be done
FLAGS
--action=(create|edit|end) Rollout action to perform
--action=(create|edit|end|view) Rollout action to perform
--branch=<value> Branch to roll out. Use with --action=create
--json Enable JSON output, non-JSON messages will be printed to stderr.
--non-interactive Run the command in non-interactive mode.
@@ -701,7 +703,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/v4.0.0/packages/eas-cli/src/commands/channel/rollout.ts)_
_See code: [src/commands/channel/rollout.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/channel/rollout.ts)_
## `eas channel:view [NAME]`
@@ -724,7 +726,7 @@ DESCRIPTION
view a channel
```
_See code: [src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/channel/view.ts)_
_See code: [src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/channel/view.ts)_
## `eas config`
@@ -745,7 +747,7 @@ DESCRIPTION
display project configuration (app.json + eas.json)
```
_See code: [src/commands/config.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/config.ts)_
_See code: [src/commands/config.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/config.ts)_
## `eas credentials`
@@ -762,7 +764,7 @@ DESCRIPTION
manage credentials
```
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/credentials.ts)_
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/credentials.ts)_
## `eas device:create`
@@ -776,7 +778,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/v4.0.0/packages/eas-cli/src/commands/device/create.ts)_
_See code: [src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/device/create.ts)_
## `eas device:delete`
@@ -796,7 +798,7 @@ DESCRIPTION
remove a registered device from your account
```
_See code: [src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/device/delete.ts)_
_See code: [src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/device/delete.ts)_
## `eas device:list`
@@ -817,7 +819,7 @@ DESCRIPTION
list all registered devices for your account
```
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/device/list.ts)_
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/device/list.ts)_
## `eas device:rename`
@@ -838,7 +840,7 @@ DESCRIPTION
rename a registered device
```
_See code: [src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/device/rename.ts)_
_See code: [src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/device/rename.ts)_
## `eas device:view [UDID]`
@@ -852,7 +854,7 @@ DESCRIPTION
view a device for your project
```
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/device/view.ts)_
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/device/view.ts)_
## `eas diagnostics`
@@ -866,7 +868,7 @@ DESCRIPTION
display environment info
```
_See code: [src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/diagnostics.ts)_
_See code: [src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/diagnostics.ts)_
## `eas help [COMMAND]`
@@ -954,7 +956,7 @@ DESCRIPTION
validate the local store configuration
```
_See code: [src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/metadata/lint.ts)_
_See code: [src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/metadata/lint.ts)_
## `eas metadata:pull`
@@ -971,7 +973,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/v4.0.0/packages/eas-cli/src/commands/metadata/pull.ts)_
_See code: [src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/metadata/pull.ts)_
## `eas metadata:push`
@@ -988,7 +990,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/v4.0.0/packages/eas-cli/src/commands/metadata/push.ts)_
_See code: [src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/metadata/push.ts)_
## `eas open`
@@ -1002,7 +1004,7 @@ DESCRIPTION
open the project page in a web browser
```
_See code: [src/commands/open.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/open.ts)_
_See code: [src/commands/open.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/open.ts)_
## `eas project:info`
@@ -1016,7 +1018,7 @@ DESCRIPTION
information about the current project
```
_See code: [src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/project/info.ts)_
_See code: [src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/project/info.ts)_
## `eas project:init`
@@ -1038,7 +1040,7 @@ ALIASES
$ eas init
```
_See code: [src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/project/init.ts)_
_See code: [src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/project/init.ts)_
## `eas secret:create`
@@ -1061,7 +1063,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/v4.0.0/packages/eas-cli/src/commands/secret/create.ts)_
_See code: [src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/secret/create.ts)_
## `eas secret:delete`
@@ -1079,7 +1081,7 @@ DESCRIPTION
delete an environment secret by ID
```
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/secret/delete.ts)_
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/secret/delete.ts)_
## `eas secret:list`
@@ -1093,7 +1095,7 @@ DESCRIPTION
list environment secrets available for your current app
```
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/secret/list.ts)_
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/secret/list.ts)_
## `eas secret:push`
@@ -1113,7 +1115,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/v4.0.0/packages/eas-cli/src/commands/secret/push.ts)_
_See code: [src/commands/secret/push.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/secret/push.ts)_
## `eas submit`
@@ -1143,7 +1145,7 @@ ALIASES
$ eas build:submit
```
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/submit.ts)_
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/submit.ts)_
## `eas update`
@@ -1152,8 +1154,8 @@ publish an update group
```
USAGE
$ eas update [--branch <value>] [--channel <value>] [-m <value>] [--republish | --input-dir <value> |
--skip-bundler] [--group <value> | | ] [--clear-cache] [-p android|ios|all] [--auto] [--private-key-path <value>]
[--json --non-interactive]
--skip-bundler] [--group <value> | | ] [--clear-cache] [-p android|ios|all] [--dev] [--auto] [--private-key-path
<value>] [--json --non-interactive]
FLAGS
-m, --message=<value> A short message describing the update
@@ -1162,6 +1164,7 @@ FLAGS
--branch=<value> Branch to publish the update group on
--channel=<value> Channel that the published update should affect
--clear-cache Clear the bundler cache before publishing
--dev Publish a development bundle
--group=<value> Update group to republish (deprecated, see republish command)
--input-dir=<value> [default: dist] Location of the bundle
--json Enable JSON output, non-JSON messages will be printed to stderr.
@@ -1176,7 +1179,7 @@ DESCRIPTION
publish an update group
```
_See code: [src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/update/index.ts)_
_See code: [src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/update/index.ts)_
## `eas update:configure`
@@ -1194,7 +1197,7 @@ DESCRIPTION
configure the project to support EAS Update
```
_See code: [src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/update/configure.ts)_
_See code: [src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/update/configure.ts)_
## `eas update:delete GROUPID`
@@ -1215,7 +1218,7 @@ DESCRIPTION
delete all the updates in an update group
```
_See code: [src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/update/delete.ts)_
_See code: [src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/update/delete.ts)_
## `eas update:list`
@@ -1237,7 +1240,7 @@ DESCRIPTION
view the recent updates
```
_See code: [src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/update/list.ts)_
_See code: [src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/update/list.ts)_
## `eas update:republish`
@@ -1264,7 +1267,53 @@ DESCRIPTION
roll back to an existing update
```
_See code: [src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/update/republish.ts)_
_See code: [src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/update/republish.ts)_
## `eas update:roll-back-to-embedded`
roll back to the embedded update
```
USAGE
$ eas update:roll-back-to-embedded [--branch <value>] [--channel <value>] [--message <value>] [-p android|ios|all] [--auto]
[--private-key-path <value>] [--json --non-interactive]
FLAGS
-p, --platform=(android|ios|all) [default: all]
--auto Use the current git branch and commit message for the EAS branch and update message
--branch=<value> Branch to publish the rollback to embedded update group on
--channel=<value> Channel that the published rollback to embedded update should affect
--json Enable JSON output, non-JSON messages will be printed to stderr.
--message=<value> A short message describing the rollback to embedded update
--non-interactive Run the command in non-interactive mode.
--private-key-path=<value> File containing the PEM-encoded private key corresponding to the certificate in
expo-updates' configuration. Defaults to a file named "private-key.pem" in the
certificate's directory.
DESCRIPTION
roll back to the embedded update
```
_See code: [src/commands/update/roll-back-to-embedded.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/update/roll-back-to-embedded.ts)_
## `eas update:rollback`
roll back to an embedded update or an existing update
```
USAGE
$ eas update:rollback [--private-key-path <value>]
FLAGS
--private-key-path=<value> File containing the PEM-encoded private key corresponding to the certificate in
expo-updates' configuration. Defaults to a file named "private-key.pem" in the
certificate's directory.
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/v5.5.0/packages/eas-cli/src/commands/update/rollback.ts)_
## `eas update:view GROUPID`
@@ -1284,7 +1333,7 @@ DESCRIPTION
update group details
```
_See code: [src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/update/view.ts)_
_See code: [src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/update/view.ts)_
## `eas webhook:create`
@@ -1305,7 +1354,7 @@ DESCRIPTION
create a webhook
```
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/webhook/create.ts)_
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/webhook/create.ts)_
## `eas webhook:delete [ID]`
@@ -1325,7 +1374,7 @@ DESCRIPTION
delete a webhook
```
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/webhook/delete.ts)_
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/webhook/delete.ts)_
## `eas webhook:list`
@@ -1343,7 +1392,7 @@ DESCRIPTION
list webhooks
```
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/webhook/list.ts)_
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/webhook/list.ts)_
## `eas webhook:update`
@@ -1365,7 +1414,7 @@ DESCRIPTION
update a webhook
```
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/webhook/update.ts)_
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/webhook/update.ts)_
## `eas webhook:view ID`
@@ -1382,7 +1431,7 @@ DESCRIPTION
view a webhook
```
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v4.0.0/packages/eas-cli/src/commands/webhook/view.ts)_
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v5.5.0/packages/eas-cli/src/commands/webhook/view.ts)_
## `eas whoami`
+1850 -181
View File
File diff suppressed because it is too large. Load diff
+8 -8
View File
@@ -1,24 +1,24 @@
{
"name": "eas-cli",
"description": "EAS command line tool",
"version": "4.0.0",
"version": "5.5.0",
"author": "Expo <[email protected]>",
"bin": {
"eas": "./bin/run"
},
"bugs": "https://github.com/expo/eas-cli/issues",
"dependencies": {
"@expo/apple-utils": "1.3.1",
"@expo/apple-utils": "1.3.2",
"@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.30",
"@expo/eas-json": "4.0.0",
"@expo/eas-build-job": "1.0.46",
"@expo/eas-json": "5.5.0",
"@expo/json-file": "8.2.37",
"@expo/multipart-body-parser": "1.1.0",
"@expo/osascript": "2.0.33",
"@expo/package-manager": "0.0.57",
"@expo/package-manager": "1.1.1",
"@expo/pkcs12": "0.0.8",
"@expo/plist": "0.0.20",
"@expo/plugin-help": "5.1.22",
@@ -27,7 +27,7 @@
"@expo/results": "1.0.0",
"@expo/rudder-sdk-node": "1.1.1",
"@expo/spawn-async": "1.7.0",
"@expo/steps": "1.0.31",
"@expo/steps": "1.0.34",
"@expo/timeago.js": "1.0.0",
"@oclif/core": "1.23.2",
"@oclif/plugin-autocomplete": "1.3.10",
@@ -50,7 +50,7 @@
"fs-extra": "10.1.0",
"getenv": "1.0.0",
"gradle-to-js": "2.0.1",
"graphql": "16.6.0",
"graphql": "16.8.1",
"graphql-tag": "2.12.6",
"https-proxy-agent": "5.0.1",
"ignore": "5.2.4",
@@ -73,7 +73,7 @@
"prompts": "2.4.2",
"qrcode-terminal": "0.12.0",
"resolve-from": "5.0.0",
"semver": "7.3.8",
"semver": "7.5.2",
"slash": "3.0.0",
"tar": "6.1.13",
"terminal-link": "2.1.1",
+3 -4
View File
@@ -1,9 +1,8 @@
import { getVcsClient } from '../vcs';
import { Client } from '../vcs/vcs';
export async function getDefaultBranchNameAsync(): Promise<string> {
export async function getDefaultBranchNameAsync(vcsClient: Client): Promise<string> {
return (
(await getVcsClient().getBranchNameAsync()) ||
`branch-${Math.random().toString(36).substring(2, 4)}`
(await vcsClient.getBranchNameAsync()) || `branch-${Math.random().toString(36).substring(2, 4)}`
);
}
@@ -8,6 +8,7 @@ import os from 'os';
import path from 'path';
import { getAppBuildGradleAsync, resolveConfigValue } from '../../../project/android/gradleUtils';
import { getVcsClient } from '../../../vcs';
import {
BumpStrategy,
bumpVersionAsync,
@@ -18,6 +19,8 @@ import {
const fsReal = jest.requireActual('fs').promises as typeof fs;
jest.mock('fs');
const vcsClient = getVcsClient();
afterAll(async () => {
// do not remove the following line
// this fixes a weird error with tempy in @expo/image-utils
@@ -191,7 +194,8 @@ describe(maybeResolveVersionsAsync, () => {
const { appVersion, appBuildVersion } = await maybeResolveVersionsAsync(
'/app',
exp,
{} as BuildProfile<Platform.ANDROID>
{} as BuildProfile<Platform.ANDROID>,
vcsClient
);
expect(appVersion).toBe('3.0.0');
expect(appBuildVersion).toBe('123');
@@ -203,7 +207,8 @@ describe(maybeResolveVersionsAsync, () => {
const { appVersion, appBuildVersion } = await maybeResolveVersionsAsync(
'/app',
exp,
{} as BuildProfile<Platform.ANDROID>
{} as BuildProfile<Platform.ANDROID>,
vcsClient
);
expect(appVersion).toBe('5.0.0');
expect(appBuildVersion).toBe('126');
+14 -2
View File
@@ -59,13 +59,22 @@ This means that it will most likely produce an AAB and you will not be able to i
await checkGoogleServicesFileAsync(ctx);
await validatePNGsForManagedProjectAsync(ctx);
const gradleContext = await resolveGradleBuildContextAsync(ctx.projectDir, buildProfile);
const gradleContext = await resolveGradleBuildContextAsync(
ctx.projectDir,
buildProfile,
ctx.vcsClient
);
if (ctx.workflow === Workflow.MANAGED) {
await ensureApplicationIdIsDefinedForManagedProjectAsync(ctx);
}
const applicationId = await getApplicationIdAsync(ctx.projectDir, ctx.exp, gradleContext);
const applicationId = await getApplicationIdAsync(
ctx.projectDir,
ctx.exp,
ctx.vcsClient,
gradleContext
);
const versionCodeOverride =
ctx.easJsonCliConfig?.appVersionSource === AppVersionSource.REMOTE
? await resolveRemoteVersionCodeAsync(ctx.graphqlClient, {
@@ -74,6 +83,7 @@ This means that it will most likely produce an AAB and you will not be able to i
exp: ctx.exp,
applicationId,
buildProfile,
vcsClient: ctx.vcsClient,
})
: undefined;
@@ -97,6 +107,7 @@ export async function prepareAndroidBuildAsync(
? false
: ctx.buildProfile.autoIncrement,
projectId: ctx.projectId,
vcsClient: ctx.vcsClient,
});
},
prepareJobAsync: async (
@@ -136,6 +147,7 @@ async function ensureAndroidCredentialsAsync(
const androidApplicationIdentifier = await getApplicationIdAsync(
ctx.projectDir,
ctx.exp,
ctx.vcsClient,
ctx.android.gradleContext
);
const provider = new AndroidCredentialsProvider(ctx.credentialsCtx, {
@@ -14,7 +14,6 @@ import slash from 'slash';
import { AndroidCredentials } from '../../credentials/android/AndroidCredentialsProvider';
import { getCustomBuildConfigPath } from '../../project/customBuildConfig';
import { getUsername } from '../../project/projectUtils';
import { getVcsClient } from '../../vcs';
import { BuildContext } from '../context';
interface JobData {
@@ -34,7 +33,7 @@ export async function prepareJobAsync(
const username = getUsername(ctx.exp, ctx.user);
const buildProfile: BuildProfile<Platform.ANDROID> = ctx.buildProfile;
const projectRootDirectory =
slash(path.relative(await getVcsClient().getRootPathAsync(), ctx.projectDir)) || '.';
slash(path.relative(await ctx.vcsClient.getRootPathAsync(), ctx.projectDir)) || '.';
const { credentials } = jobData;
const buildCredentials = credentials
? {
@@ -66,6 +65,8 @@ export async function prepareJobAsync(
builderEnvironment: {
image: buildProfile.image,
node: buildProfile.node,
pnpm: buildProfile.pnpm,
bun: buildProfile.bun,
yarn: buildProfile.yarn,
ndk: buildProfile.ndk,
expoCli: buildProfile.expoCli,
@@ -11,6 +11,7 @@ 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';
import { BumpStrategy, bumpVersionAsync, bumpVersionInAppJsonAsync } from './version';
export async function syncProjectConfigurationAsync(
@@ -20,14 +21,16 @@ export async function syncProjectConfigurationAsync(
exp,
localAutoIncrement,
projectId,
vcsClient,
}: {
projectDir: string;
exp: ExpoConfig;
localAutoIncrement?: AndroidVersionAutoIncrement;
projectId: string;
vcsClient: Client;
}
): Promise<void> {
const workflow = await resolveWorkflowAsync(projectDir, Platform.ANDROID);
const workflow = await resolveWorkflowAsync(projectDir, Platform.ANDROID, vcsClient);
const versionBumpStrategy = resolveVersionBumpStrategy(localAutoIncrement ?? false);
if (workflow === Workflow.GENERIC) {
@@ -18,6 +18,7 @@ import {
} from '../../project/android/gradleUtils';
import { getNextVersionCode } from '../../project/android/versions';
import { resolveWorkflowAsync } from '../../project/workflow';
import { Client } from '../../vcs/vcs';
import { updateAppJsonConfigAsync } from '../utils/appJson';
import { bumpAppVersionAsync, ensureStaticConfigExists } from '../utils/version';
@@ -96,9 +97,10 @@ export async function bumpVersionInAppJsonAsync({
export async function maybeResolveVersionsAsync(
projectDir: string,
exp: ExpoConfig,
buildProfile: BuildProfile<Platform.ANDROID>
buildProfile: BuildProfile<Platform.ANDROID>,
vcsClient: Client
): Promise<{ appVersion?: string; appBuildVersion?: string }> {
const workflow = await resolveWorkflowAsync(projectDir, Platform.ANDROID);
const workflow = await resolveWorkflowAsync(projectDir, Platform.ANDROID, vcsClient);
if (workflow === Workflow.GENERIC) {
const buildGradle = await getAppBuildGradleAsync(projectDir);
try {
@@ -183,12 +185,14 @@ export async function resolveRemoteVersionCodeAsync(
exp,
applicationId,
buildProfile,
vcsClient,
}: {
projectDir: string;
projectId: string;
exp: ExpoConfig;
applicationId: string;
buildProfile: BuildProfile<Platform.ANDROID>;
vcsClient: Client;
}
): Promise<string> {
const remoteVersions = await AppVersionQuery.latestVersionAsync(
@@ -198,7 +202,7 @@ export async function resolveRemoteVersionCodeAsync(
applicationId
);
const localVersions = await maybeResolveVersionsAsync(projectDir, exp, buildProfile);
const localVersions = await maybeResolveVersionsAsync(projectDir, exp, buildProfile, vcsClient);
let currentBuildVersion: string;
if (remoteVersions?.buildVersion) {
currentBuildVersion = remoteVersions.buildVersion;
+7 -87
View File
@@ -1,5 +1,5 @@
import { ArchiveSource, ArchiveSourceType, Job, Metadata, Platform } from '@expo/eas-build-job';
import { CredentialsSource, EasJsonAccessor, EasJsonUtils, ResourceClass } from '@expo/eas-json';
import { CredentialsSource } from '@expo/eas-json';
import assert from 'assert';
import chalk from 'chalk';
import cliProgress from 'cli-progress';
@@ -17,7 +17,6 @@ import {
BuildFragment,
BuildParamsInput,
BuildPriority,
BuildResourceClass,
BuildStatus,
UploadSessionType,
} from '../graphql/generated';
@@ -30,13 +29,11 @@ import {
appPlatformEmojis,
requestedPlatformDisplayNames,
} from '../platform';
import { confirmAsync } from '../prompts';
import { uploadFileAtPathToGCSAsync } from '../uploads';
import { formatBytes } from '../utils/files';
import { printJsonOnlyOutput } from '../utils/json';
import { createProgressTracker } from '../utils/progress';
import { sleepAsync } from '../utils/promise';
import { getVcsClient } from '../vcs';
import { BuildContext } from './context';
import {
EasBuildDownForMaintenanceError,
@@ -125,9 +122,10 @@ export async function prepareBuildRequestForPlatformAsync<
}
);
if (await getVcsClient().isCommitRequiredAsync()) {
if (await ctx.vcsClient.isCommitRequiredAsync()) {
Log.addNewLineIfNone();
await reviewAndCommitChangesAsync(
ctx.vcsClient,
`[EAS Build] Run EAS Build for ${requestedPlatformDisplayNames[ctx.platform as Platform]}`,
{ nonInteractive: ctx.nonInteractive }
);
@@ -137,7 +135,7 @@ export async function prepareBuildRequestForPlatformAsync<
if (ctx.localBuildOptions.localBuildMode === LocalBuildMode.LOCAL_BUILD_PLUGIN) {
projectArchive = {
type: ArchiveSourceType.PATH,
path: (await makeProjectTarballAsync()).path,
path: (await makeProjectTarballAsync(ctx.vcsClient)).path,
};
} else if (ctx.localBuildOptions.localBuildMode === LocalBuildMode.INTERNAL) {
projectArchive = {
@@ -245,7 +243,7 @@ async function uploadProjectAsync<TPlatform extends Platform>(
'https://expo.fyi/eas-build-archive'
)}`
);
const projectTarball = await makeProjectTarballAsync();
const projectTarball = await makeProjectTarballAsync(ctx.vcsClient);
if (projectTarball.size > 1024 * 1024 * 100) {
Log.warn(
@@ -335,12 +333,7 @@ export type MaybeBuildFragment = BuildFragment | null;
export async function waitForBuildEndAsync(
graphqlClient: ExpoGraphqlClient,
{
buildIds,
accountName,
projectDir,
nonInteractive,
}: { buildIds: string[]; accountName: string; projectDir: string; nonInteractive: boolean },
{ buildIds, accountName }: { buildIds: string[]; accountName: string },
{ intervalSec = 10 } = {}
): Promise<MaybeBuildFragment[]> {
let spinner;
@@ -357,10 +350,7 @@ export async function waitForBuildEndAsync(
const builds = await getBuildsSafelyAsync(graphqlClient, buildIds);
const { refetch } =
builds.length === 1
? await handleSingleBuildProgressAsync(
{ build: builds[0], accountName, projectDir, nonInteractive },
{ spinner }
)
? await handleSingleBuildProgressAsync({ build: builds[0], accountName }, { spinner })
: await handleMultipleBuildsProgressAsync({ builds }, { spinner, originalSpinnerText });
if (!refetch) {
return builds;
@@ -398,13 +388,9 @@ async function handleSingleBuildProgressAsync(
{
build,
accountName,
projectDir,
nonInteractive,
}: {
build: MaybeBuildFragment;
accountName: string;
projectDir: string;
nonInteractive: boolean;
},
{ spinner }: { spinner: Ora }
): Promise<BuildProgressResult> {
@@ -458,54 +444,6 @@ async function handleSingleBuildProgressAsync(
);
}
if (
build.platform === AppPlatform.Ios &&
[BuildResourceClass.IosIntelLarge, BuildResourceClass.IosIntelMedium].includes(
build.resourceClass
)
) {
let askToSwitchToM1 = false;
if (
build.priority === BuildPriority.High &&
build.estimatedWaitTimeLeftSeconds >= /* 10 minutes */ 10 * 60
) {
Log.newLine();
Log.warn(
`Warning: Priority queue wait time for legacy iOS Intel workers is longer than usual (more than 10 minutes).`
);
Log.warn(`We recommend switching to the new, faster M1 workers for iOS builds.`);
Log.warn(
learnMore('https://blog.expo.dev/m1-workers-on-eas-build-dcaa2c1333ad', {
learnMoreMessage: 'Learn more on switching to M1 workers.',
})
);
askToSwitchToM1 = true;
} else if (
build.priority !== BuildPriority.High &&
build.estimatedWaitTimeLeftSeconds >= /* 120 minutes */ 120 * 60
) {
Log.newLine();
Log.warn(
`Warning: Free tier queue wait time for legacy iOS Intel workers is longer than usual.`
);
Log.warn(`We recommend switching to the new, faster M1 workers for iOS builds.`);
Log.warn(
learnMore('https://blog.expo.dev/m1-workers-on-eas-build-dcaa2c1333ad', {
learnMoreMessage: 'Learn more on switching to M1 workers.',
})
);
askToSwitchToM1 = true;
}
if (!nonInteractive && askToSwitchToM1) {
const shouldSwitchToM1 = await confirmAsync({
message: `Switch iOS builds to M1 workers (modifies build profiles in eas.json)?`,
});
if (shouldSwitchToM1) {
await updateIosBuildProfilesToUseM1WorkersAsync(projectDir);
}
}
}
Log.newLine();
Log.log(`Waiting in ${priorityToQueueDisplayName[build.priority]}`);
queueProgressBar.start(
@@ -654,21 +592,3 @@ function formatAccountSubscriptionsUrl(accountName: string): string {
getExpoWebsiteBaseUrl()
).toString();
}
async function updateIosBuildProfilesToUseM1WorkersAsync(projectDir: string): Promise<void> {
const easJsonAccessor = EasJsonAccessor.fromProjectPath(projectDir);
await easJsonAccessor.readRawJsonAsync();
const profileNames = await EasJsonUtils.getBuildProfileNamesAsync(easJsonAccessor);
easJsonAccessor.patch(easJsonRawObject => {
for (const profileName of profileNames) {
easJsonRawObject.build[profileName].ios = {
...easJsonRawObject.build[profileName].ios,
resourceClass: ResourceClass.M_MEDIUM,
};
}
return easJsonRawObject;
});
await easJsonAccessor.writeAsync();
Log.withTick('Updated eas.json. Your next builds will run on M1 workers.');
}
+15 -10
View File
@@ -6,12 +6,13 @@ import fs from 'fs-extra';
import Log, { learnMore } from '../log';
import { resolveWorkflowAsync } from '../project/workflow';
import { easCliVersion } from '../utils/easCli';
import { getVcsClient } from '../vcs';
import { Client } from '../vcs/vcs';
import { maybeBailOnRepoStatusAsync, reviewAndCommitChangesAsync } from './utils/repository';
interface ConfigureParams {
projectDir: string;
nonInteractive: boolean;
vcsClient: Client;
}
export async function easJsonExistsAsync(projectDir: string): Promise<boolean> {
@@ -36,14 +37,18 @@ export async function ensureProjectConfiguredAsync(
return true;
}
async function configureAsync({ projectDir, nonInteractive }: ConfigureParams): Promise<void> {
await maybeBailOnRepoStatusAsync();
async function configureAsync({
projectDir,
nonInteractive,
vcsClient,
}: ConfigureParams): Promise<void> {
await maybeBailOnRepoStatusAsync(vcsClient);
await createEasJsonAsync(projectDir);
await createEasJsonAsync(projectDir, vcsClient);
if (await getVcsClient().isCommitRequiredAsync()) {
if (await vcsClient.isCommitRequiredAsync()) {
Log.newLine();
await reviewAndCommitChangesAsync('Configure EAS Build', {
await reviewAndCommitChangesAsync(vcsClient, 'Configure EAS Build', {
nonInteractive,
});
}
@@ -92,20 +97,20 @@ const EAS_JSON_BARE_DEFAULT: EasJson = {
},
};
async function createEasJsonAsync(projectDir: string): Promise<void> {
async function createEasJsonAsync(projectDir: string, vcsClient: Client): Promise<void> {
const easJsonPath = EasJsonAccessor.formatEasJsonPath(projectDir);
const hasAndroidNativeProject =
(await resolveWorkflowAsync(projectDir, Platform.ANDROID)) === Workflow.GENERIC;
(await resolveWorkflowAsync(projectDir, Platform.ANDROID, vcsClient)) === Workflow.GENERIC;
const hasIosNativeProject =
(await resolveWorkflowAsync(projectDir, Platform.IOS)) === Workflow.GENERIC;
(await resolveWorkflowAsync(projectDir, Platform.IOS, vcsClient)) === Workflow.GENERIC;
const easJson =
hasAndroidNativeProject || hasIosNativeProject
? EAS_JSON_BARE_DEFAULT
: EAS_JSON_MANAGED_DEFAULT;
await fs.writeFile(easJsonPath, `${JSON.stringify(easJson, null, 2)}\n`);
await getVcsClient().trackFileAsync(easJsonPath);
await vcsClient.trackFileAsync(easJsonPath);
Log.withTick(
`Generated ${chalk.bold('eas.json')}. ${learnMore(
'https://docs.expo.dev/build-reference/eas-json/'
+5
View File
@@ -1,6 +1,7 @@
import { ExpoConfig } from '@expo/config';
import { Platform, Workflow } from '@expo/eas-build-job';
import { BuildProfile, EasJson } from '@expo/eas-json';
import { NodePackageManager } from '@expo/package-manager';
import { Analytics, AnalyticsEventProperties } from '../analytics/AnalyticsManager';
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
@@ -11,6 +12,7 @@ import { GradleBuildContext } from '../project/android/gradle';
import { CustomBuildConfigMetadata } from '../project/customBuildConfig';
import { XcodeBuildContext } from '../project/ios/scheme';
import { Actor } from '../user/User';
import { Client } from '../vcs/vcs';
import { LocalBuildOptions } from './local';
export type CommonContext<T extends Platform> = Omit<BuildContext<T>, 'android' | 'ios'>;
@@ -55,4 +57,7 @@ export interface BuildContext<T extends Platform> {
customBuildConfigMetadata?: CustomBuildConfigMetadata;
android: T extends Platform.ANDROID ? AndroidBuildContext : undefined;
ios: T extends Platform.IOS ? IosBuildContext : undefined;
developmentClient: boolean;
requiredPackageManager: NodePackageManager['name'] | null;
vcsClient: Client;
}
+17 -1
View File
@@ -1,6 +1,7 @@
import { Platform } from '@expo/eas-build-job';
import { BuildProfile, EasJson, ResourceClass } from '@expo/eas-json';
import JsonFile from '@expo/json-file';
import { resolvePackageManager } from '@expo/package-manager';
import getenv from 'getenv';
import resolveFrom from 'resolve-from';
import { v4 as uuidv4 } from 'uuid';
@@ -13,6 +14,7 @@ import { CustomBuildConfigMetadata } from '../project/customBuildConfig';
import { getOwnerAccountForProjectIdAsync } from '../project/projectUtils';
import { resolveWorkflowAsync } from '../project/workflow';
import { Actor } from '../user/User';
import { Client } from '../vcs/vcs';
import { createAndroidContextAsync } from './android/build';
import { BuildContext, CommonContext } from './context';
import { createIosContextAsync } from './ios/build';
@@ -34,6 +36,7 @@ export async function createBuildContextAsync<T extends Platform>({
actor,
graphqlClient,
analytics,
vcsClient,
getDynamicPrivateProjectConfigAsync,
customBuildConfigMetadata,
}: {
@@ -51,15 +54,24 @@ export async function createBuildContextAsync<T extends Platform>({
actor: Actor;
graphqlClient: ExpoGraphqlClient;
analytics: Analytics;
vcsClient: Client;
getDynamicPrivateProjectConfigAsync: DynamicConfigContextFn;
customBuildConfigMetadata?: CustomBuildConfigMetadata;
}): Promise<BuildContext<T>> {
const { exp, projectId } = await getDynamicPrivateProjectConfigAsync({ env: buildProfile.env });
const projectName = exp.slug;
const account = await getOwnerAccountForProjectIdAsync(graphqlClient, projectId);
const workflow = await resolveWorkflowAsync(projectDir, platform);
const workflow = await resolveWorkflowAsync(projectDir, platform, vcsClient);
const accountId = account.id;
const runFromCI = getenv.boolish('CI', false);
const developmentClient =
buildProfile.developmentClient ??
(platform === Platform.ANDROID
? (buildProfile as BuildProfile<Platform.ANDROID>)?.gradleCommand === ':app:assembleDebug'
: (buildProfile as BuildProfile<Platform.IOS>)?.buildConfiguration === 'Debug') ??
false;
const requiredPackageManager = resolvePackageManager(projectDir);
const credentialsCtx = new CredentialsContext({
projectInfo: { exp, projectId },
@@ -70,6 +82,7 @@ export async function createBuildContextAsync<T extends Platform>({
analytics,
env: buildProfile.env,
easJsonCliConfig,
vcsClient,
});
const devClientProperties = getDevClientEventProperties({
@@ -116,10 +129,13 @@ export async function createBuildContextAsync<T extends Platform>({
user: actor,
graphqlClient,
analytics,
vcsClient,
workflow,
message,
runFromCI,
customBuildConfigMetadata,
developmentClient,
requiredPackageManager,
};
if (platform === Platform.ANDROID) {
const common = commonContext as CommonContext<Platform.ANDROID>;
@@ -6,6 +6,7 @@ import os from 'os';
import type { XCBuildConfiguration } from 'xcode';
import { readPlistAsync } from '../../../utils/plist';
import { getVcsClient } from '../../../vcs';
import {
BumpStrategy,
bumpVersionAsync,
@@ -18,6 +19,8 @@ import {
jest.mock('fs');
const vcsClient = getVcsClient();
const getXCBuildConfigurationFromPbxproj = jest.spyOn(
IOSConfig.Target,
'getXCBuildConfigurationFromPbxproj'
@@ -262,7 +265,7 @@ describe(readBuildNumberAsync, () => {
describe('bare project', () => {
it('reads the build number from native code', async () => {
const exp = initBareWorkflowProject();
const buildNumber = await readBuildNumberAsync('/app', exp, {});
const buildNumber = await readBuildNumberAsync('/app', exp, {}, vcsClient);
expect(buildNumber).toBe('1');
});
});
@@ -270,7 +273,7 @@ describe(readBuildNumberAsync, () => {
describe('managed project', () => {
it('reads the build number from expo config', async () => {
const exp = initManagedProject();
const buildNumber = await readBuildNumberAsync('/app', exp, {});
const buildNumber = await readBuildNumberAsync('/app', exp, {}, vcsClient);
expect(buildNumber).toBe('1');
});
});
@@ -280,16 +283,21 @@ describe(readShortVersionAsync, () => {
describe('bare project', () => {
it('reads the short version from native code', async () => {
const exp = initBareWorkflowProject();
const appVersion = await readShortVersionAsync('/app', exp, {});
const appVersion = await readShortVersionAsync('/app', exp, {}, vcsClient);
expect(appVersion).toBe('1.0.0');
});
it('evaluates interpolated build number', async () => {
const exp = initBareWorkflowProject({
appVersion: '$(CURRENT_PROJECT_VERSION)',
});
const buildNumber = await readShortVersionAsync('/app', exp, {
CURRENT_PROJECT_VERSION: '1.0.0',
});
const buildNumber = await readShortVersionAsync(
'/app',
exp,
{
CURRENT_PROJECT_VERSION: '1.0.0',
},
vcsClient
);
expect(buildNumber).toBe('1.0.0');
});
@@ -299,9 +307,14 @@ describe(readShortVersionAsync, () => {
});
await expect(
readShortVersionAsync('/app', exp, {
CURRENT_PROJECT_VERSION: '0.0.7.1.028',
})
readShortVersionAsync(
'/app',
exp,
{
CURRENT_PROJECT_VERSION: '0.0.7.1.028',
},
vcsClient
)
).rejects.toThrowError(
'CFBundleShortVersionString (version field in app.json/app.config.js) must be a period-separated list of three non-negative integers. Current value: 0.0.7.1.028'
);
@@ -311,7 +324,7 @@ describe(readShortVersionAsync, () => {
describe('managed project', () => {
it('reads the version from app config', async () => {
const exp = initBareWorkflowProject();
const appVersion = await readShortVersionAsync('/app', exp, {});
const appVersion = await readShortVersionAsync('/app', exp, {}, vcsClient);
expect(appVersion).toBe('1.0.0');
});
});
+4
View File
@@ -39,6 +39,7 @@ export async function createIosContextAsync(
projectDir: ctx.projectDir,
nonInteractive: ctx.nonInteractive,
exp: ctx.exp,
vcsClient: ctx.vcsClient,
},
buildProfile
);
@@ -47,6 +48,7 @@ export async function createIosContextAsync(
exp: ctx.exp,
xcodeBuildContext,
env: buildProfile.env,
vcsClient: ctx.vcsClient,
});
const applicationTarget = findApplicationTarget(targets);
const buildNumberOverride =
@@ -57,6 +59,7 @@ export async function createIosContextAsync(
exp: ctx.exp,
applicationTarget,
buildProfile,
vcsClient: ctx.vcsClient,
})
: undefined;
return {
@@ -86,6 +89,7 @@ export async function prepareIosBuildAsync(
? false
: ctx.buildProfile.autoIncrement,
projectId: ctx.projectId,
vcsClient: ctx.vcsClient,
});
},
prepareJobAsync: async (
@@ -55,6 +55,5 @@ export async function ensureIosCredentialsForBuildResignAsync(
}
function shouldProvideCredentials(buildCtx: BuildContext<Platform.IOS>): boolean {
const isCustomBuild = buildCtx.buildProfile.config !== undefined;
return !buildCtx.buildProfile.simulator && !isCustomBuild;
return !buildCtx.buildProfile.simulator && !buildCtx.buildProfile.withoutCredentials;
}
+3 -2
View File
@@ -16,7 +16,6 @@ import { IosCredentials, TargetCredentials } from '../../credentials/ios/types';
import { IosJobSecretsInput } from '../../graphql/generated';
import { getCustomBuildConfigPath } from '../../project/customBuildConfig';
import { getUsername } from '../../project/projectUtils';
import { getVcsClient } from '../../vcs';
import { BuildContext } from '../context';
interface JobData {
@@ -37,7 +36,7 @@ export async function prepareJobAsync(
const username = getUsername(ctx.exp, ctx.user);
const buildProfile: BuildProfile<Platform.IOS> = ctx.buildProfile;
const projectRootDirectory =
slash(path.relative(await getVcsClient().getRootPathAsync(), ctx.projectDir)) || '.';
slash(path.relative(await ctx.vcsClient.getRootPathAsync(), ctx.projectDir)) || '.';
const buildCredentials: Ios.BuildSecrets['buildCredentials'] = {};
if (jobData.credentials) {
const targetNames = Object.keys(jobData.credentials);
@@ -58,6 +57,8 @@ export async function prepareJobAsync(
builderEnvironment: {
image: buildProfile.image,
node: buildProfile.node,
pnpm: buildProfile.pnpm,
bun: buildProfile.bun,
yarn: buildProfile.yarn,
bundler: buildProfile.bundler,
cocoapods: buildProfile.cocoapods,
@@ -7,6 +7,7 @@ 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';
import { BumpStrategy, bumpVersionAsync, bumpVersionInAppJsonAsync } from './version';
export async function syncProjectConfigurationAsync(
@@ -17,20 +18,22 @@ export async function syncProjectConfigurationAsync(
targets,
localAutoIncrement,
projectId,
vcsClient,
}: {
projectDir: string;
exp: ExpoConfig;
targets: Target[];
localAutoIncrement?: IosVersionAutoIncrement;
projectId: string;
vcsClient: Client;
}
): Promise<void> {
const workflow = await resolveWorkflowAsync(projectDir, Platform.IOS);
const workflow = await resolveWorkflowAsync(projectDir, Platform.IOS, vcsClient);
const versionBumpStrategy = resolveVersionBumpStrategy(localAutoIncrement ?? false);
if (workflow === Workflow.GENERIC) {
if (isExpoUpdatesInstalled(projectDir)) {
await syncUpdatesConfigurationAsync(graphqlClient, projectDir, exp, projectId);
await syncUpdatesConfigurationAsync(graphqlClient, vcsClient, projectDir, exp, projectId);
}
await bumpVersionAsync({ projectDir, exp, bumpStrategy: versionBumpStrategy, targets });
} else {
+19 -9
View File
@@ -19,6 +19,7 @@ import { resolveWorkflowAsync } from '../../project/workflow';
import { promptAsync } from '../../prompts';
import uniqBy from '../../utils/expodash/uniqBy';
import { readPlistAsync, writePlistAsync } from '../../utils/plist';
import { Client } from '../../vcs/vcs';
import { updateAppJsonConfigAsync } from '../utils/appJson';
import { bumpAppVersionAsync, ensureStaticConfigExists } from '../utils/version';
@@ -110,9 +111,10 @@ function validateShortVersion(shortVersion: string | undefined): void {
export async function readShortVersionAsync(
projectDir: string,
exp: ExpoConfig,
buildSettings: XCBuildConfiguration['buildSettings']
buildSettings: XCBuildConfiguration['buildSettings'],
vcsClient: Client
): Promise<string | undefined> {
const workflow = await resolveWorkflowAsync(projectDir, Platform.IOS);
const workflow = await resolveWorkflowAsync(projectDir, Platform.IOS, vcsClient);
if (workflow === Workflow.GENERIC) {
const infoPlist = await readInfoPlistAsync(projectDir, buildSettings);
@@ -131,9 +133,10 @@ export async function readShortVersionAsync(
export async function readBuildNumberAsync(
projectDir: string,
exp: ExpoConfig,
buildSettings: XCBuildConfiguration['buildSettings']
buildSettings: XCBuildConfiguration['buildSettings'],
vcsClient: Client
): Promise<string | undefined> {
const workflow = await resolveWorkflowAsync(projectDir, Platform.IOS);
const workflow = await resolveWorkflowAsync(projectDir, Platform.IOS, vcsClient);
if (workflow === Workflow.GENERIC) {
const infoPlist = await readInfoPlistAsync(projectDir, buildSettings);
return (
@@ -147,7 +150,8 @@ export async function readBuildNumberAsync(
export async function maybeResolveVersionsAsync(
projectDir: string,
exp: ExpoConfig,
targets: Target[]
targets: Target[],
vcsClient: Client
): Promise<{ appVersion?: string; appBuildVersion?: string }> {
const applicationTarget = findApplicationTarget(targets);
try {
@@ -155,12 +159,14 @@ export async function maybeResolveVersionsAsync(
appBuildVersion: await readBuildNumberAsync(
projectDir,
exp,
applicationTarget.buildSettings ?? {}
applicationTarget.buildSettings ?? {},
vcsClient
),
appVersion: await readShortVersionAsync(
projectDir,
exp,
applicationTarget.buildSettings ?? {}
applicationTarget.buildSettings ?? {},
vcsClient
),
};
} catch (err: any) {
@@ -278,12 +284,14 @@ export async function resolveRemoteBuildNumberAsync(
exp,
applicationTarget,
buildProfile,
vcsClient,
}: {
projectDir: string;
projectId: string;
exp: ExpoConfig;
applicationTarget: Target;
buildProfile: BuildProfile<Platform.IOS>;
vcsClient: Client;
}
): Promise<string> {
const remoteVersions = await AppVersionQuery.latestVersionAsync(
@@ -296,12 +304,14 @@ export async function resolveRemoteBuildNumberAsync(
const localBuildNumber = await readBuildNumberAsync(
projectDir,
exp,
applicationTarget.buildSettings ?? {}
applicationTarget.buildSettings ?? {},
vcsClient
);
const localShortVersion = await readShortVersionAsync(
projectDir,
exp,
applicationTarget.buildSettings ?? {}
applicationTarget.buildSettings ?? {},
vcsClient
);
let currentBuildVersion: string;
if (remoteVersions?.buildVersion) {
+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.33';
const PLUGIN_PACKAGE_VERSION = '1.0.44';
export enum LocalBuildMode {
/**
+9 -7
View File
@@ -15,7 +15,6 @@ import {
readReleaseChannelSafelyAsync as readIosReleaseChannelSafelyAsync,
} from '../update/ios/UpdatesModule';
import { easCliVersion } from '../utils/easCli';
import { getVcsClient } from '../vcs';
import { maybeResolveVersionsAsync as maybeResolveAndroidVersionsAsync } from './android/version';
import { BuildContext } from './context';
import { maybeResolveVersionsAsync as maybeResolveIosVersionsAsync } from './ios/version';
@@ -24,7 +23,6 @@ import { LocalBuildMode } from './local';
export async function collectMetadataAsync<T extends Platform>(
ctx: BuildContext<T>
): Promise<Metadata> {
const vcsClient = getVcsClient();
const channelOrReleaseChannel = await resolveChannelOrReleaseChannelAsync(ctx);
const distribution =
('simulator' in ctx.buildProfile && ctx.buildProfile.simulator
@@ -44,14 +42,14 @@ export async function collectMetadataAsync<T extends Platform>(
appName: ctx.exp.name,
appIdentifier: resolveAppIdentifier(ctx),
buildProfile: ctx.buildProfileName,
gitCommitHash: await vcsClient.getCommitHashAsync(),
gitCommitHash: await ctx.vcsClient.getCommitHashAsync(),
gitCommitMessage: truncateGitCommitMessage(
(await vcsClient.getLastCommitMessageAsync()) ?? undefined
(await ctx.vcsClient.getLastCommitMessageAsync()) ?? undefined
),
isGitWorkingTreeDirty:
ctx.localBuildOptions.localBuildMode === LocalBuildMode.INTERNAL
? false
: await vcsClient.hasUncommittedChangesAsync(),
: await ctx.vcsClient.hasUncommittedChangesAsync(),
username: getUsername(ctx.exp, ctx.user),
message: ctx.message,
...(ctx.platform === Platform.IOS && {
@@ -63,6 +61,8 @@ export async function collectMetadataAsync<T extends Platform>(
runFromCI: ctx.runFromCI,
buildMode: ctx.buildProfile.config ? BuildMode.CUSTOM : BuildMode.BUILD,
customWorkflowName: ctx.customBuildConfigMetadata?.workflowName,
developmentClient: ctx.developmentClient,
requiredPackageManager: ctx.requiredPackageManager ?? undefined,
};
return sanitizeMetadata(metadata);
}
@@ -75,7 +75,8 @@ async function maybeResolveVersionsAsync<T extends Platform>(
const resolvedVersion = await maybeResolveIosVersionsAsync(
ctx.projectDir,
ctx.exp,
iosContext.ios.targets
iosContext.ios.targets,
ctx.vcsClient
);
if (iosContext.ios.buildNumberOverride) {
return {
@@ -89,7 +90,8 @@ async function maybeResolveVersionsAsync<T extends Platform>(
const resolvedVersion = await maybeResolveAndroidVersionsAsync(
ctx.projectDir,
ctx.exp,
androidCtx.buildProfile
androidCtx.buildProfile,
ctx.vcsClient
);
if (androidCtx.android.versionCodeOverride) {
return {
+53 -11
View File
@@ -1,3 +1,4 @@
import { ExpoConfig } from '@expo/config-types';
import { Platform, Workflow } from '@expo/eas-build-job';
import {
AppVersionSource,
@@ -13,6 +14,7 @@ import chalk from 'chalk';
import nullthrows from 'nullthrows';
import { Analytics } from '../analytics/AnalyticsManager';
import { createAndLinkChannelAsync, doesChannelExistAsync } from '../channel/queries';
import { DynamicConfigContextFn } from '../commandUtils/context/DynamicProjectConfigContextField';
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
import {
@@ -38,9 +40,9 @@ import {
import { checkExpoSdkIsSupportedAsync } from '../project/expoSdk';
import { validateMetroConfigForManagedWorkflowAsync } from '../project/metroConfig';
import {
installExpoUpdatesAsync,
isExpoUpdatesInstalledAsDevDependency,
isExpoUpdatesInstalledOrAvailable,
isUsingEASUpdate,
validateAppVersionRuntimePolicySupportAsync,
} from '../project/projectUtils';
import {
@@ -57,13 +59,14 @@ import {
waitToCompleteAsync as waitForSubmissionsToCompleteAsync,
} from '../submit/submit';
import { printSubmissionDetailsUrls } from '../submit/utils/urls';
import { ensureEASUpdateIsConfiguredAsync } from '../update/configure';
import { validateBuildProfileConfigMatchesProjectConfigAsync } from '../update/utils';
import { Actor } from '../user/User';
import { downloadAndMaybeExtractAppAsync } from '../utils/download';
import { truthy } from '../utils/expodash/filter';
import { printJsonOnlyOutput } from '../utils/json';
import { ProfileData, getProfilesAsync } from '../utils/profiles';
import { getVcsClient } from '../vcs';
import { Client } from '../vcs/vcs';
import { prepareAndroidBuildAsync } from './android/build';
import { BuildRequestSender, MaybeBuildFragment, waitForBuildEndAsync } from './build';
import { ensureProjectConfiguredAsync } from './configure';
@@ -95,17 +98,19 @@ export interface BuildFlags {
export async function runBuildAndSubmitAsync(
graphqlClient: ExpoGraphqlClient,
analytics: Analytics,
vcsClient: Client,
projectDir: string,
flags: BuildFlags,
actor: Actor,
getDynamicPrivateProjectConfigAsync: DynamicConfigContextFn
): Promise<void> {
await getVcsClient().ensureRepoExistsAsync();
await ensureRepoIsCleanAsync(flags.nonInteractive);
await vcsClient.ensureRepoExistsAsync();
await ensureRepoIsCleanAsync(vcsClient, flags.nonInteractive);
await ensureProjectConfiguredAsync({
projectDir,
nonInteractive: flags.nonInteractive,
vcsClient,
});
const easJsonAccessor = EasJsonAccessor.fromProjectPath(projectDir);
const easJsonCliConfig: EasJson['cli'] =
@@ -117,6 +122,7 @@ export async function runBuildAndSubmitAsync(
easJsonAccessor,
platforms,
profileName: flags.profile ?? undefined,
projectDir,
});
Log.log(
`Loaded "env" configuration for the "${buildProfiles[0].profileName}" profile: ${
@@ -130,6 +136,7 @@ export async function runBuildAndSubmitAsync(
projectDir,
nonInteractive: flags.nonInteractive,
buildProfiles,
vcsClient,
});
const customBuildConfigMetadataByPlatform: { [p in AppPlatform]?: CustomBuildConfigMetadata } =
@@ -159,6 +166,7 @@ export async function runBuildAndSubmitAsync(
actor,
graphqlClient,
analytics,
vcsClient,
getDynamicPrivateProjectConfigAsync,
customBuildConfigMetadata: customBuildConfigMetadataByPlatform[platform],
});
@@ -183,6 +191,7 @@ export async function runBuildAndSubmitAsync(
platforms,
profileName: flags.submitProfile,
type: 'submit',
projectDir,
});
for (const startedBuild of startedBuilds) {
const submitProfile = nullthrows(
@@ -222,8 +231,6 @@ export async function runBuildAndSubmitAsync(
const builds = await waitForBuildEndAsync(graphqlClient, {
buildIds: startedBuilds.map(({ build }) => build.id),
accountName,
projectDir,
nonInteractive: flags.nonInteractive,
});
if (!flags.json) {
printBuildResults(builds);
@@ -269,6 +276,7 @@ async function prepareAndStartBuildAsync({
actor,
graphqlClient,
analytics,
vcsClient,
getDynamicPrivateProjectConfigAsync,
customBuildConfigMetadata,
}: {
@@ -280,6 +288,7 @@ async function prepareAndStartBuildAsync({
actor: Actor;
graphqlClient: ExpoGraphqlClient;
analytics: Analytics;
vcsClient: Client;
getDynamicPrivateProjectConfigAsync: DynamicConfigContextFn;
customBuildConfigMetadata?: CustomBuildConfigMetadata;
}): Promise<{ build: BuildFragment | undefined; buildCtx: BuildContext<Platform> }> {
@@ -298,6 +307,7 @@ async function prepareAndStartBuildAsync({
actor,
graphqlClient,
analytics,
vcsClient,
getDynamicPrivateProjectConfigAsync,
customBuildConfigMetadata,
});
@@ -320,11 +330,27 @@ async function prepareAndStartBuildAsync({
);
if (buildProfile.profile.channel) {
await validateExpoUpdatesInstalledAsProjectDependencyAsync({
graphqlClient,
exp: buildCtx.exp,
projectId: buildCtx.projectId,
projectDir,
vcsClient: buildCtx.vcsClient,
sdkVersion: buildCtx.exp.sdkVersion,
nonInteractive: flags.nonInteractive,
buildProfile,
});
if (isUsingEASUpdate(buildCtx.exp, buildCtx.projectId)) {
const doesChannelExist = await doesChannelExistAsync(graphqlClient, {
appId: buildCtx.projectId,
channelName: buildProfile.profile.channel,
});
if (!doesChannelExist) {
await createAndLinkChannelAsync(graphqlClient, {
appId: buildCtx.projectId,
channelName: buildProfile.profile.channel,
});
}
}
}
await validateAppVersionRuntimePolicySupportAsync(buildCtx.projectDir, buildCtx.exp);
@@ -391,6 +417,7 @@ async function prepareAndStartSubmissionAsync({
analytics: buildCtx.analytics,
projectId: buildCtx.projectId,
exp: buildCtx.exp,
vcsClient: buildCtx.vcsClient,
});
if (moreBuilds) {
@@ -447,12 +474,20 @@ async function maybeDownloadAndRunSimulatorBuildsAsync(
}
async function validateExpoUpdatesInstalledAsProjectDependencyAsync({
exp,
graphqlClient,
projectId,
projectDir,
vcsClient,
buildProfile,
nonInteractive,
sdkVersion,
}: {
graphqlClient: ExpoGraphqlClient;
exp: ExpoConfig;
projectId: string;
projectDir: string;
vcsClient: Client;
buildProfile: ProfileData<'build'>;
nonInteractive: boolean;
sdkVersion?: string;
@@ -467,18 +502,25 @@ async function validateExpoUpdatesInstalledAsProjectDependencyAsync({
);
} else if (nonInteractive) {
Log.warn(
`The build profile "${buildProfile.profileName}" has specified the channel "${buildProfile.profile.channel}", but the "expo-updates" package hasn't been installed. To use channels for your builds, install the "expo-updates" package by running "npx expo install expo-updates".`
`The build profile "${buildProfile.profileName}" has specified the channel "${buildProfile.profile.channel}", but the "expo-updates" package hasn't been installed. To use channels for your builds, install the "expo-updates" package by running "npx expo install expo-updates" followed by "eas update:configure".`
);
} else {
Log.warn(
`The build profile "${buildProfile.profileName}" specifies the channel "${buildProfile.profile.channel}", but the "expo-updates" package is missing. To use channels in your builds, install the "expo-updates" package.`
`The build profile "${buildProfile.profileName}" specifies the channel "${buildProfile.profile.channel}", but the "expo-updates" package is missing. To use channels in your builds, install the "expo-updates" package and run "eas update:configure".`
);
const installExpoUpdates = await confirmAsync({
message: `Would you like to install the "expo-updates" package?`,
message: `Would you like to install the "expo-updates" package and configure EAS Update now?`,
});
if (installExpoUpdates) {
await installExpoUpdatesAsync(projectDir, { silent: false });
Log.withTick('Installed expo-updates');
await ensureEASUpdateIsConfiguredAsync(graphqlClient, {
exp,
projectId,
projectDir,
platform: RequestedPlatform.All,
vcsClient,
});
Log.withTick('Installed expo-updates and configured EAS Update.');
throw new Error('Command must be re-run to pick up new updates configuration.');
}
}
}
@@ -10,15 +10,17 @@ import { resolveWorkflowAsync } from '../../project/workflow';
import { confirmAsync } from '../../prompts';
import { expoCommandAsync } from '../../utils/expoCli';
import { ProfileData } from '../../utils/profiles';
import { getVcsClient } from '../../vcs';
import { Client } from '../../vcs/vcs';
import { reviewAndCommitChangesAsync } from './repository';
export async function ensureExpoDevClientInstalledForDevClientBuildsAsync({
projectDir,
vcsClient,
nonInteractive = false,
buildProfiles = [],
}: {
projectDir: string;
vcsClient: Client;
nonInteractive?: boolean;
buildProfiles?: ProfileData<'build'>[];
}): Promise<void> {
@@ -41,7 +43,7 @@ export async function ensureExpoDevClientInstalledForDevClientBuildsAsync({
);
const workflowPerPlatformList = await Promise.all(
platformsToCheck.map(platform => resolveWorkflowAsync(projectDir, platform))
platformsToCheck.map(platform => resolveWorkflowAsync(projectDir, platform, vcsClient))
);
Log.newLine();
@@ -62,7 +64,7 @@ export async function ensureExpoDevClientInstalledForDevClientBuildsAsync({
instructions: 'The command will abort unless you agree.',
});
if (install) {
await installExpoDevClientAsync(projectDir, { nonInteractive });
await installExpoDevClientAsync(projectDir, vcsClient, { nonInteractive });
} else {
Errors.error(`Install ${chalk.bold('expo-dev-client')} manually and come back later.`, {
exit: 1,
@@ -100,6 +102,7 @@ async function isExpoDevClientInstalledAsync(projectDir: string): Promise<boolea
async function installExpoDevClientAsync(
projectDir: string,
vcsClient: Client,
{ nonInteractive }: { nonInteractive: boolean }
): Promise<void> {
Log.newLine();
@@ -107,8 +110,8 @@ async function installExpoDevClientAsync(
Log.newLine();
await expoCommandAsync(projectDir, ['install', 'expo-dev-client']);
Log.newLine();
if (await getVcsClient().isCommitRequiredAsync()) {
await reviewAndCommitChangesAsync('Install expo-dev-client', {
if (await vcsClient.isCommitRequiredAsync()) {
await reviewAndCommitChangesAsync(vcsClient, 'Install expo-dev-client', {
nonInteractive,
});
}
+29 -20
View File
@@ -10,10 +10,10 @@ import { confirmAsync, promptAsync } from '../../prompts';
import { formatBytes } from '../../utils/files';
import { getTmpDirectory } from '../../utils/paths';
import { endTimer, formatMilliseconds, startTimer } from '../../utils/timer';
import { getVcsClient } from '../../vcs';
import { Client } from '../../vcs/vcs';
export async function maybeBailOnRepoStatusAsync(): Promise<void> {
if (!(await getVcsClient().isCommitRequiredAsync())) {
export async function maybeBailOnRepoStatusAsync(vcsClient: Client): Promise<void> {
if (!(await vcsClient.isCommitRequiredAsync())) {
return;
}
Log.addNewLineIfNone();
@@ -32,8 +32,11 @@ export async function maybeBailOnRepoStatusAsync(): Promise<void> {
}
}
export async function ensureRepoIsCleanAsync(nonInteractive = false): Promise<void> {
if (!(await getVcsClient().isCommitRequiredAsync())) {
export async function ensureRepoIsCleanAsync(
vcsClient: Client,
nonInteractive = false
): Promise<void> {
if (!(await vcsClient.isCommitRequiredAsync())) {
return;
}
Log.addNewLineIfNone();
@@ -50,19 +53,22 @@ export async function ensureRepoIsCleanAsync(nonInteractive = false): Promise<vo
message: `Commit changes to git?`,
});
if (answer) {
await commitPromptAsync({ commitAllFiles: true });
await commitPromptAsync(vcsClient, { commitAllFiles: true });
} else {
throw new Error('Commit all changes. Aborting...');
}
}
export async function commitPromptAsync({
initialCommitMessage,
commitAllFiles,
}: {
initialCommitMessage?: string;
commitAllFiles?: boolean;
} = {}): Promise<void> {
export async function commitPromptAsync(
vcsClient: Client,
{
initialCommitMessage,
commitAllFiles,
}: {
initialCommitMessage?: string;
commitAllFiles?: boolean;
} = {}
): Promise<void> {
const { message } = await promptAsync({
type: 'text',
name: 'message',
@@ -70,14 +76,16 @@ export async function commitPromptAsync({
initial: initialCommitMessage,
validate: (input: string) => input !== '',
});
await getVcsClient().commitAsync({
await vcsClient.commitAsync({
commitAllFiles,
commitMessage: message,
nonInteractive: false,
});
}
export async function makeProjectTarballAsync(): Promise<{ path: string; size: number }> {
export async function makeProjectTarballAsync(
vcsClient: Client
): Promise<{ path: string; size: number }> {
const spinner = ora('Compressing project files');
await fs.mkdirp(getTmpDirectory());
@@ -99,7 +107,7 @@ export async function makeProjectTarballAsync(): Promise<{ path: string; size: n
startTimer(compressTimerLabel);
try {
await getVcsClient().makeShallowCopyAsync(shallowClonePath);
await vcsClient.makeShallowCopyAsync(shallowClonePath);
await tar.create({ cwd: shallowClonePath, file: tarPath, prefix: 'project', gzip: true }, [
'.',
]);
@@ -133,11 +141,12 @@ enum ShouldCommitChanges {
}
export async function reviewAndCommitChangesAsync(
vcsClient: Client,
initialCommitMessage: string,
{ nonInteractive, askedFirstTime = true }: { nonInteractive: boolean; askedFirstTime?: boolean }
): Promise<void> {
if (process.env.EAS_BUILD_AUTOCOMMIT) {
await getVcsClient().commitAsync({
await vcsClient.commitAsync({
commitMessage: initialCommitMessage,
commitAllFiles: false,
nonInteractive,
@@ -171,11 +180,11 @@ export async function reviewAndCommitChangesAsync(
"Aborting, run the command again once you're ready. Make sure to commit any changes you've made."
);
} else if (selected === ShouldCommitChanges.Yes) {
await commitPromptAsync({ initialCommitMessage });
await commitPromptAsync(vcsClient, { initialCommitMessage });
Log.withTick('Committed changes.');
} else if (selected === ShouldCommitChanges.ShowDiffFirst) {
await getVcsClient().showDiffAsync();
await reviewAndCommitChangesAsync(initialCommitMessage, {
await vcsClient.showDiffAsync();
await reviewAndCommitChangesAsync(vcsClient, initialCommitMessage, {
nonInteractive,
askedFirstTime: false,
});
@@ -7,21 +7,13 @@ import Log, { link } from '../../log';
type AndroidResourceClass = Exclude<
ResourceClass,
| ResourceClass.M1_EXPERIMENTAL
| ResourceClass.M1_MEDIUM
| ResourceClass.M1_LARGE
| ResourceClass.INTEL_MEDIUM
| ResourceClass.M_MEDIUM
| ResourceClass.M_LARGE
ResourceClass.M1_MEDIUM | ResourceClass.M_MEDIUM | ResourceClass.M_LARGE
>;
const iosResourceClassToBuildResourceClassMapping: Record<ResourceClass, BuildResourceClass> = {
[ResourceClass.DEFAULT]: BuildResourceClass.IosDefault,
[ResourceClass.LARGE]: BuildResourceClass.IosLarge,
[ResourceClass.M1_EXPERIMENTAL]: BuildResourceClass.IosMMedium,
[ResourceClass.M1_MEDIUM]: BuildResourceClass.IosMMedium,
[ResourceClass.M1_LARGE]: BuildResourceClass.IosMLarge,
[ResourceClass.INTEL_MEDIUM]: BuildResourceClass.IosIntelMedium,
[ResourceClass.MEDIUM]: BuildResourceClass.IosMedium,
[ResourceClass.M_MEDIUM]: BuildResourceClass.IosMMedium,
[ResourceClass.M_LARGE]: BuildResourceClass.IosMLarge,
@@ -57,15 +49,7 @@ export async function resolveBuildResourceClassAsync<T extends Platform>(
}
function resolveAndroidResourceClass(selectedResourceClass?: ResourceClass): BuildResourceClass {
if (
selectedResourceClass &&
[
ResourceClass.M1_EXPERIMENTAL,
ResourceClass.M1_MEDIUM,
ResourceClass.M1_LARGE,
ResourceClass.INTEL_MEDIUM,
].includes(selectedResourceClass)
) {
if (selectedResourceClass && ResourceClass.M1_MEDIUM === selectedResourceClass) {
throw new Error(`Resource class ${selectedResourceClass} is only available for iOS builds`);
}
@@ -88,7 +72,7 @@ function resolveIosResourceClass(
);
}
if ([ResourceClass.M1_EXPERIMENTAL, ResourceClass.M1_MEDIUM].includes(resourceClass)) {
if (ResourceClass.M1_MEDIUM === resourceClass) {
Log.warn(
`Resource class ${chalk.bold(resourceClass)} is deprecated. Use ${chalk.bold(
'm-medium'
@@ -96,7 +80,7 @@ function resolveIosResourceClass(
);
}
if ([ResourceClass.M_LARGE, ResourceClass.M1_LARGE].includes(resourceClass)) {
if (ResourceClass.M_LARGE === resourceClass) {
Log.warn(
`Resource class ${chalk.bold(resourceClass)} is deprecated. Use ${chalk.bold(
'large'
+2 -3
View File
@@ -6,7 +6,6 @@ import semver from 'semver';
import Log, { learnMore } from '../log';
import { isPNGAsync } from '../utils/image';
import { getVcsClient } from '../vcs';
import { CommonContext } from './context';
export function checkNodeEnvVariable(ctx: CommonContext<Platform>): void {
@@ -28,12 +27,12 @@ export async function checkGoogleServicesFileAsync<T extends Platform>(
if (!googleServicesFilePath) {
return;
}
const rootDir = path.normalize(await getVcsClient().getRootPathAsync());
const rootDir = path.normalize(await ctx.vcsClient.getRootPathAsync());
const absGoogleServicesFilePath = path.resolve(ctx.projectDir, googleServicesFilePath);
if (
(await fs.pathExists(absGoogleServicesFilePath)) &&
(!isInsideDirectory(absGoogleServicesFilePath, rootDir) ||
(await getVcsClient().isFileIgnoredAsync(path.relative(rootDir, absGoogleServicesFilePath))))
(await ctx.vcsClient.isFileIgnoredAsync(path.relative(rootDir, absGoogleServicesFilePath))))
) {
Log.warn(
`File specified via "${ctx.platform}.googleServicesFile" field in your app.json is not checked in to your repository and won't be uploaded to the builder.`
@@ -0,0 +1,22 @@
import { BranchBasicInfo, ChannelBasicInfo, UpdateChannelInfoWithBranches } from '../utils';
export const testChannelBasicInfo: ChannelBasicInfo = {
id: '9309afc2-9752-40db-8ef7-4abc10744c61',
name: 'production',
branchMapping:
'{"data":[{"branchId":"754bf17f-efc0-46ab-8a59-a03f20e53e9b","branchMappingLogic":{"operand":0.15,"clientKey":"rolloutToken","branchMappingOperator":"hash_lt"}},{"branchId":"6941a8dd-5c0a-48bc-8876-f49c88ed419f","branchMappingLogic":"true"}],"version":0}',
};
export const testBasicBranchInfo1: BranchBasicInfo = {
id: '754bf17f-efc0-46ab-8a59-a03f20e53e9b',
name: 'wrong-channel',
};
export const testBasicBranchInfo2: BranchBasicInfo = {
id: '6941a8dd-5c0a-48bc-8876-f49c88ed419f',
name: 'production',
};
export const channelInfoWithBranches: UpdateChannelInfoWithBranches<BranchBasicInfo> = {
...testChannelBasicInfo,
updateBranches: [testBasicBranchInfo1, testBasicBranchInfo2],
};
@@ -1,21 +1,41 @@
import { rolloutBranchMapping, standardBranchMapping } from '../../rollout/__tests__/fixtures';
import {
emptyBranchMapping,
rolloutBranchMapping,
standardBranchMapping,
} from '../../rollout/__tests__/fixtures';
import {
BranchMappingValidationError,
assertVersion,
getAlwaysTrueBranchMapping,
getBranchMapping,
getEmptyBranchMapping,
getStandardBranchId,
isAlwaysTrueBranchMapping,
isEmptyBranchMapping,
} from '../branch-mapping';
import { testChannelObject } from './fixtures';
import { testChannelBasicInfo } from './branch-mapping-fixtures';
describe(assertVersion, () => {
it('throws if the branch mapping is not the correct version', () => {
expect(() => assertVersion(testChannelObject, 5)).toThrowError(BranchMappingValidationError);
expect(() => assertVersion(testChannelBasicInfo, 5)).toThrowError(BranchMappingValidationError);
});
it('asserts the correct version', () => {
assertVersion(testChannelObject, 0);
expect(getBranchMapping(testChannelObject.branchMapping).version).toBe(0);
assertVersion(testChannelBasicInfo, 0);
expect(getBranchMapping(testChannelBasicInfo.branchMapping).version).toBe(0);
});
});
describe(getEmptyBranchMapping, () => {
it('gets an empty branch mapping', () => {
expect(isEmptyBranchMapping(getEmptyBranchMapping())).toBe(true);
});
});
describe(isEmptyBranchMapping, () => {
it('detects empty branch mappings', () => {
expect(isEmptyBranchMapping(emptyBranchMapping)).toBe(true);
expect(isEmptyBranchMapping(standardBranchMapping)).toBe(false);
expect(isEmptyBranchMapping(rolloutBranchMapping)).toBe(false);
});
});
@@ -23,6 +43,7 @@ describe(isAlwaysTrueBranchMapping, () => {
it('detects always true branch mappings', () => {
expect(isAlwaysTrueBranchMapping(standardBranchMapping)).toBe(true);
expect(isAlwaysTrueBranchMapping(rolloutBranchMapping)).toBe(false);
expect(isAlwaysTrueBranchMapping(emptyBranchMapping)).toBe(false);
});
});
@@ -35,10 +56,12 @@ describe(getAlwaysTrueBranchMapping, () => {
describe(getStandardBranchId, () => {
it('throws if the branch mapping is not a standard mapping', () => {
expect(() => getStandardBranchId(testChannelObject)).toThrowError(BranchMappingValidationError);
expect(() => getStandardBranchId(testChannelBasicInfo)).toThrowError(
BranchMappingValidationError
);
});
it('gets a standard branch id', () => {
const channelObjectWithStandardMapping = { ...testChannelObject };
const channelObjectWithStandardMapping = { ...testChannelBasicInfo };
channelObjectWithStandardMapping.branchMapping = JSON.stringify(standardBranchMapping);
expect(getStandardBranchId(channelObjectWithStandardMapping)).toBe(
standardBranchMapping.data[0].branchId
@@ -124,6 +124,7 @@ export const testChannelObject: UpdateChannelObject = {
id: '9309afc2-9752-40db-8ef7-4abc10744c61',
name: 'production',
createdAt: '2023-05-16T21:26:16.946Z',
updatedAt: '2023-05-16T21:26:16.946Z',
branchMapping:
'{"data":[{"branchId":"754bf17f-efc0-46ab-8a59-a03f20e53e9b","branchMappingLogic":{"operand":0.15,"clientKey":"rolloutToken","branchMappingOperator":"hash_lt"}},{"branchId":"6941a8dd-5c0a-48bc-8876-f49c88ed419f","branchMappingLogic":"true"}],"version":0}',
updateBranches: [testUpdateBranch1, testUpdateBranch2],
@@ -0,0 +1,57 @@
import { format } from '@expo/timeago.js';
import { getAlwaysTrueBranchMapping, getEmptyBranchMapping } from '../branch-mapping';
import { getDescriptionByBranchId } from '../print-utils';
import { testChannelObject, testUpdateBranch1, testUpdateBranch2 } from './fixtures';
describe(getDescriptionByBranchId, () => {
it('should get descriptions for multiple branches with multiple update groups', () => {
const descriptionByBranchId = getDescriptionByBranchId(testChannelObject);
expect(Object.values(descriptionByBranchId)).toHaveLength(2);
expect(descriptionByBranchId[testUpdateBranch1.id]).toEqual({
branch: 'wrong-channel',
branchRolloutPercentage: 15,
update: {
codeSigningKey: undefined,
group: '16ca6dba-e63b-48b0-baa3-15a894ee9434',
isRollBackToEmbedded: false,
message: `"fix bug" (${format('2023-07-17T22:48:59.278Z', 'en_US')} by quintest113)`,
platforms: 'android, ios',
runtimeVersion: 'exposdk:48.0.0',
},
});
expect(descriptionByBranchId[testUpdateBranch2.id]).toEqual({
branch: 'production',
branchRolloutPercentage: 85,
update: {
codeSigningKey: undefined,
group: 'e40ad156-e9af-4cc2-8e9d-c7b5c328db48',
isRollBackToEmbedded: false,
message: `"fix bug" (${format('2023-06-23T23:37:10.004Z', 'en_US')} by quintest113)`,
platforms: 'android, ios',
runtimeVersion: 'exposdk:48.0.0',
},
});
});
it('should get descriptions for branches with no updates', () => {
const noUpdatesBranch = { ...testUpdateBranch1, updateGroups: [] };
const oneBranchChannel = {
...testChannelObject,
updateBranches: [noUpdatesBranch],
branchMapping: JSON.stringify(getAlwaysTrueBranchMapping(noUpdatesBranch.id)),
};
const descriptionByBranchId = getDescriptionByBranchId(oneBranchChannel);
expect(Object.values(descriptionByBranchId)).toHaveLength(1);
expect(descriptionByBranchId[testUpdateBranch1.id]).toEqual({ branch: 'wrong-channel' });
});
it('should get descriptions for no branches', () => {
const noBranchChannel = {
...testChannelObject,
updateBranches: [],
branchMapping: JSON.stringify(getEmptyBranchMapping()),
};
const descriptionByBranchId = getDescriptionByBranchId(noBranchChannel);
expect(Object.values(descriptionByBranchId)).toHaveLength(0);
});
});
@@ -1,11 +1,11 @@
import { getUpdateBranch } from '../utils';
import { testChannelObject, testUpdateBranch1 } from './fixtures';
import { channelInfoWithBranches, testBasicBranchInfo1 } from './branch-mapping-fixtures';
describe(getUpdateBranch, () => {
it('gets the update branch', () => {
expect(getUpdateBranch(testChannelObject, '754bf17f-efc0-46ab-8a59-a03f20e53e9b')).toBe(
testUpdateBranch1
expect(getUpdateBranch(channelInfoWithBranches, '754bf17f-efc0-46ab-8a59-a03f20e53e9b')).toBe(
testBasicBranchInfo1
);
expect(() => getUpdateBranch(testChannelObject, 'not-a-branch-ID')).toThrow();
expect(() => getUpdateBranch(channelInfoWithBranches, 'not-a-branch-ID')).toThrow();
});
});
+27 -4
View File
@@ -1,4 +1,4 @@
import { UpdateChannelBasicInfoFragment } from '../graphql/generated';
import { ChannelBasicInfo } from './utils';
// TODO(quin): move this into a common package with www
export type BranchMappingOperator =
@@ -45,6 +45,18 @@ export type AlwaysTrueBranchMapping = {
];
};
export type EmptyBranchMapping = {
version: number;
data: [];
};
export function getEmptyBranchMapping(): EmptyBranchMapping {
return {
version: 0,
data: [],
};
}
export function getAlwaysTrueBranchMapping(branchId: string): AlwaysTrueBranchMapping {
return {
version: 0,
@@ -57,17 +69,28 @@ export function getAlwaysTrueBranchMapping(branchId: string): AlwaysTrueBranchMa
};
}
export function hasStandardBranchMap(channelInfo: UpdateChannelBasicInfoFragment): boolean {
export function hasEmptyBranchMap(channelInfo: ChannelBasicInfo): boolean {
const branchMapping = getBranchMapping(channelInfo.branchMapping);
return isEmptyBranchMapping(branchMapping);
}
export function hasStandardBranchMap(channelInfo: ChannelBasicInfo): boolean {
const branchMapping = getBranchMapping(channelInfo.branchMapping);
return isAlwaysTrueBranchMapping(branchMapping);
}
export function getStandardBranchId(channelInfo: UpdateChannelBasicInfoFragment): string {
export function getStandardBranchId(channelInfo: ChannelBasicInfo): string {
const branchMapping = getBranchMapping(channelInfo.branchMapping);
assertAlwaysTrueBranchMapping(branchMapping);
return getBranchIdFromStandardMapping(branchMapping);
}
export function isEmptyBranchMapping(
branchMapping: BranchMapping
): branchMapping is EmptyBranchMapping {
return branchMapping.data.length === 0;
}
export function isAlwaysTrueBranchMapping(
branchMapping: BranchMapping
): branchMapping is AlwaysTrueBranchMapping {
@@ -137,7 +160,7 @@ function isVersion(branchMapping: BranchMapping, version: number): boolean {
return branchMapping.version === version;
}
export function assertVersion(channelInfo: UpdateChannelBasicInfoFragment, version: number): void {
export function assertVersion(channelInfo: ChannelBasicInfo, version: number): void {
const branchMapping = getBranchMapping(channelInfo.branchMapping);
if (!isVersion(branchMapping, version)) {
throw new BranchMappingValidationError(
+42 -26
View File
@@ -1,4 +1,3 @@
import assert from 'assert';
import chalk from 'chalk';
import { UpdateChannelObject } from '../graphql/queries/ChannelQuery';
@@ -9,19 +8,37 @@ import {
formatBranch,
getUpdateGroupDescriptionsWithBranch,
} from '../update/utils';
import { assertVersion, hasStandardBranchMap } from './branch-mapping';
import { assertVersion, hasEmptyBranchMap, hasStandardBranchMap } from './branch-mapping';
/**
* Log all the branches associated with the channel and their most recent update group
*/
export function logChannelDetails(channel: UpdateChannelObject): void {
assertVersion(channel, 0);
assert(
hasStandardBranchMap(channel) || isRollout(channel),
'Only standard branch mappings and rollouts are supported.'
);
const doesSupportMapping =
hasEmptyBranchMap(channel) || hasStandardBranchMap(channel) || isRollout(channel);
if (!doesSupportMapping) {
Log.log(chalk.dim('Custom branch mapping detected.'));
return;
}
const branchDescription = channel.updateBranches.flatMap(branch => {
const updateGroupWithBranchDescriptions = getUpdateGroupDescriptionsWithBranch(
branch.updateGroups
const branchDescriptionByBranchId = getDescriptionByBranchId(channel);
const entries = Object.entries(branchDescriptionByBranchId);
if (entries.length === 0) {
Log.log(chalk.dim('No branches are pointed to this channel.'));
} else {
Log.log(
entries
.map(([_branchId, description]) => formatBranch(description))
.join(`\n\n${chalk.dim('———')}\n\n`)
);
}
}
export function getDescriptionByBranchId(
channel: UpdateChannelObject
): Record<string, FormattedBranchDescription> {
return channel.updateBranches.reduce((acc, branch) => {
const maybeRollout = isRollout(channel) ? getRollout(channel) : null;
let maybePercentOnBranch: number | undefined = undefined;
if (maybeRollout) {
@@ -31,22 +48,21 @@ export function logChannelDetails(channel: UpdateChannelObject): void {
: 100 - maybeRollout.percentRolledOut;
}
return updateGroupWithBranchDescriptions.map(
({ branch, ...updateGroup }): FormattedBranchDescription => ({
branch,
branchRolloutPercentage: maybePercentOnBranch,
update: updateGroup,
})
if (branch.updateGroups.length === 0) {
acc[branch.id] = { branch: branch.name, branchRolloutPercentage: maybePercentOnBranch };
return acc;
}
const updateGroupsWithBranchDescriptions = getUpdateGroupDescriptionsWithBranch(
branch.updateGroups
);
});
if (branchDescription.length === 0) {
Log.log(chalk.dim('No branches are pointed to this channel.'));
} else {
Log.log(
branchDescription
.map(description => formatBranch(description))
.join(`\n\n${chalk.dim('———')}\n\n`)
);
}
// display the most recent update group
const updateGroupWithBranchDescription = updateGroupsWithBranchDescriptions[0];
const { branch: branchName, ...updateGroup } = updateGroupWithBranchDescription;
acc[branch.id] = {
branch: branchName,
branchRolloutPercentage: maybePercentOnBranch,
update: updateGroup,
};
return acc;
}, {} as Record<string, FormattedBranchDescription>);
}
+103
View File
@@ -2,6 +2,8 @@ import chalk from 'chalk';
import { print } from 'graphql';
import gql from 'graphql-tag';
import { createUpdateBranchOnAppAsync } from '../branch/queries';
import { BranchNotFoundError } from '../branch/utils';
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
import { PaginatedQueryOptions } from '../commandUtils/pagination';
import { withErrorHandlingAsync } from '../graphql/client';
@@ -15,13 +17,16 @@ import { BranchQuery, UpdateBranchOnChannelObject } from '../graphql/queries/Bra
import { ChannelQuery, UpdateChannelObject } from '../graphql/queries/ChannelQuery';
import { UpdateChannelBasicInfoFragmentNode } from '../graphql/types/UpdateChannelBasicInfo';
import Log from '../log';
import { getDisplayNameForProjectIdAsync } from '../project/projectUtils';
import formatFields from '../utils/formatFields';
import { printJsonOnlyOutput } from '../utils/json';
import {
paginatedQueryWithConfirmPromptAsync,
paginatedQueryWithSelectPromptAsync,
} from '../utils/queries';
import { ChannelNotFoundError } from './errors';
import { logChannelDetails } from './print-utils';
import { ChannelBasicInfo } from './utils';
export const CHANNELS_LIMIT = 25;
@@ -264,3 +269,101 @@ export async function ensureChannelExistsAsync(
}
}
}
export async function doesChannelExistAsync(
graphqlClient: ExpoGraphqlClient,
{ appId, channelName }: { appId: string; channelName: string }
): Promise<boolean> {
try {
await ChannelQuery.viewUpdateChannelAsync(graphqlClient, {
appId,
channelName,
});
} catch (err) {
if (err instanceof ChannelNotFoundError) {
return false;
}
throw err;
}
return true;
}
/**
*
* Creates a channel and links it to a branch with the same name.
*
* @param appId the app ID, also known as the project ID
* @param channelName the name of the channel to create
* @param shouldPrintJson print only the JSON output
*/
export async function createAndLinkChannelAsync(
graphqlClient: ExpoGraphqlClient,
{
appId,
channelName,
shouldPrintJson,
}: { appId: string; channelName: string; shouldPrintJson?: boolean }
): Promise<ChannelBasicInfo> {
let branchId: string;
let branchMessage: string;
try {
const branch = await BranchQuery.getBranchByNameAsync(graphqlClient, {
appId,
name: channelName,
});
branchId = branch.id;
branchMessage = `We found a branch with the same name`;
} catch (error) {
if (error instanceof BranchNotFoundError) {
const newBranch = await createUpdateBranchOnAppAsync(graphqlClient, {
appId,
name: channelName,
});
branchId = newBranch.id;
branchMessage = `We also went ahead and made a branch with the same name`;
} else {
throw error;
}
}
const {
updateChannel: { createUpdateChannelForApp: newChannel },
} = await createChannelOnAppAsync(graphqlClient, {
appId,
channelName,
branchId,
});
if (!newChannel) {
throw new Error(
`Could not create channel with name ${channelName} on project with id ${appId}`
);
}
if (shouldPrintJson) {
printJsonOnlyOutput(newChannel);
} else {
Log.addNewLineIfNone();
Log.withTick(
`Created a new channel on project ${chalk.bold(
await getDisplayNameForProjectIdAsync(graphqlClient, appId)
)}`
);
Log.log(
formatFields([
{ label: 'Name', value: newChannel.name },
{ label: 'ID', value: newChannel.id },
])
);
Log.addNewLineIfNone();
Log.withTick(`${branchMessage} and have pointed the channel at it.`);
Log.log(
formatFields([
{ label: 'Name', value: newChannel.name },
{ label: 'ID', value: branchId },
])
);
}
return newChannel;
}
+19 -7
View File
@@ -1,18 +1,30 @@
import { UpdateBranchObject, UpdateChannelObject } from '../graphql/queries/ChannelQuery';
export type ChannelBasicInfo = {
id: string;
name: string;
branchMapping: string;
};
export type BranchBasicInfo = {
id: string;
name: string;
};
function getUpdateBranchNullable(
channel: UpdateChannelObject,
export type UpdateChannelInfoWithBranches<Branch extends BranchBasicInfo> = ChannelBasicInfo & {
updateBranches: Branch[];
};
function getUpdateBranchNullable<Branch extends BranchBasicInfo>(
channel: UpdateChannelInfoWithBranches<Branch>,
branchId: string
): UpdateBranchObject | null {
): Branch | null {
const updateBranches = channel.updateBranches;
const updateBranch = updateBranches.find(branch => branch.id === branchId);
return updateBranch ?? null;
}
export function getUpdateBranch(
channel: UpdateChannelObject,
export function getUpdateBranch<Branch extends BranchBasicInfo>(
channel: UpdateChannelInfoWithBranches<Branch>,
branchId: string
): UpdateBranchObject {
): Branch {
const updateBranch = getUpdateBranchNullable(channel, branchId);
if (!updateBranch) {
throw new Error(
@@ -22,6 +22,7 @@ import { OptionalPrivateProjectConfigContextField } from './context/OptionalPriv
import { PrivateProjectConfigContextField } from './context/PrivateProjectConfigContextField';
import ProjectDirContextField from './context/ProjectDirContextField';
import SessionManagementContextField from './context/SessionManagementContextField';
import VcsClientContextField from './context/VcsClientContextField';
import { EasCommandError } from './errors';
export type ContextInput<
@@ -101,6 +102,9 @@ export default abstract class EasCommand extends Command {
Analytics: {
analytics: new AnalyticsContextField(),
},
Vcs: {
vcsClient: new VcsClientContextField(),
},
};
/**
@@ -0,0 +1,9 @@
import { getVcsClient } from '../../vcs';
import { Client } from '../../vcs/vcs';
import ContextField from './ContextField';
export default class VcsClientContextField extends ContextField<Client> {
async getValueAsync(): Promise<Client> {
return getVcsClient();
}
}
@@ -27,6 +27,7 @@ export default class BranchCreate extends EasCommand {
static override contextDefinition = {
...this.ContextOptions.ProjectConfig,
...this.ContextOptions.LoggedIn,
...this.ContextOptions.Vcs,
};
async runAsync(): Promise<void> {
@@ -37,6 +38,7 @@ export default class BranchCreate extends EasCommand {
const {
privateProjectConfig: { projectId },
loggedIn: { graphqlClient },
vcsClient,
} = await this.getContextAsync(BranchCreate, {
nonInteractive,
});
@@ -56,7 +58,7 @@ export default class BranchCreate extends EasCommand {
type: 'text',
name: 'name',
message: 'Provide a branch name:',
initial: await getDefaultBranchNameAsync(),
initial: await getDefaultBranchNameAsync(vcsClient),
validate: value => (value ? true : validationMessage),
}));
}
@@ -139,6 +139,7 @@ export default class BuildCancel extends EasCommand {
static override contextDefinition = {
...this.ContextOptions.ProjectConfig,
...this.ContextOptions.LoggedIn,
...this.ContextOptions.Vcs,
};
async runAsync(): Promise<void> {
@@ -16,7 +16,6 @@ import {
ensureUseClassicUpdatesIsRemovedAsync,
} from '../../update/configure';
import { syncUpdatesConfigurationAsync as syncIosUpdatesConfigurationAsync } from '../../update/ios/UpdatesModule';
import { getVcsClient } from '../../vcs';
export default class BuildConfigure extends EasCommand {
static override description = 'configure the project to support EAS Build';
@@ -32,6 +31,7 @@ export default class BuildConfigure extends EasCommand {
static override contextDefinition = {
...this.ContextOptions.ProjectConfig,
...this.ContextOptions.LoggedIn,
...this.ContextOptions.Vcs,
};
async runAsync(): Promise<void> {
@@ -39,6 +39,7 @@ export default class BuildConfigure extends EasCommand {
const {
privateProjectConfig: { exp, projectId, projectDir },
loggedIn: { graphqlClient },
vcsClient,
} = await this.getContextAsync(BuildConfigure, {
nonInteractive: false,
});
@@ -47,7 +48,9 @@ export default class BuildConfigure extends EasCommand {
'💡 The following process will configure your iOS and/or Android project to be compatible with EAS Build. These changes only apply to your local project files and you can safely revert them at any time.'
);
await getVcsClient().ensureRepoExistsAsync();
// BuildConfigure.ContextOptions.Vcs.client.getValueAsync()
await vcsClient.ensureRepoExistsAsync();
const expoUpdatesIsInstalled = isExpoUpdatesInstalled(projectDir);
@@ -64,6 +67,7 @@ export default class BuildConfigure extends EasCommand {
const didCreateEasJson = await ensureProjectConfiguredAsync({
projectDir,
nonInteractive: false,
vcsClient,
});
if (didCreateEasJson && isUsingEASUpdate(exp, projectId)) {
if (exp.updates?.useClassicUpdates) {
@@ -78,16 +82,22 @@ export default class BuildConfigure extends EasCommand {
// configure expo-updates
if (expoUpdatesIsInstalled) {
if ([RequestedPlatform.Android, RequestedPlatform.All].includes(platform)) {
const workflow = await resolveWorkflowAsync(projectDir, Platform.ANDROID);
const workflow = await resolveWorkflowAsync(projectDir, Platform.ANDROID, vcsClient);
if (workflow === Workflow.GENERIC) {
await syncAndroidUpdatesConfigurationAsync(graphqlClient, projectDir, exp, projectId);
}
}
if ([RequestedPlatform.Ios, RequestedPlatform.All].includes(platform)) {
const workflow = await resolveWorkflowAsync(projectDir, Platform.IOS);
const workflow = await resolveWorkflowAsync(projectDir, Platform.IOS, vcsClient);
if (workflow === Workflow.GENERIC) {
await syncIosUpdatesConfigurationAsync(graphqlClient, projectDir, exp, projectId);
await syncIosUpdatesConfigurationAsync(
graphqlClient,
vcsClient,
projectDir,
exp,
projectId
);
}
}
}
@@ -106,6 +106,7 @@ export default class Build extends EasCommand {
...this.ContextOptions.DynamicProjectConfig,
...this.ContextOptions.ProjectDir,
...this.ContextOptions.Analytics,
...this.ContextOptions.Vcs,
};
async runAsync(): Promise<void> {
@@ -121,6 +122,7 @@ export default class Build extends EasCommand {
getDynamicPrivateProjectConfigAsync,
projectDir,
analytics,
vcsClient,
} = await this.getContextAsync(Build, {
nonInteractive: flags.nonInteractive,
});
@@ -141,6 +143,7 @@ export default class Build extends EasCommand {
await runBuildAndSubmitAsync(
graphqlClient,
analytics,
vcsClient,
projectDir,
flagsWithPlatform,
actor,
@@ -11,7 +11,6 @@ import Log from '../../log';
import { ora } from '../../ora';
import { RequestedPlatform } from '../../platform';
import { getTmpDirectory } from '../../utils/paths';
import { getVcsClient } from '../../vcs';
enum InspectStage {
ARCHIVE = 'archive',
@@ -67,6 +66,7 @@ export default class BuildInspect extends EasCommand {
...this.ContextOptions.DynamicProjectConfig,
...this.ContextOptions.ProjectDir,
...this.ContextOptions.Analytics,
...this.ContextOptions.Vcs,
};
async runAsync(): Promise<void> {
@@ -76,6 +76,7 @@ export default class BuildInspect extends EasCommand {
getDynamicPrivateProjectConfigAsync,
projectDir,
analytics,
vcsClient,
} = await this.getContextAsync(BuildInspect, {
nonInteractive: false,
});
@@ -92,15 +93,15 @@ export default class BuildInspect extends EasCommand {
await this.prepareOutputDirAsync(outputDirectory, flags.force);
if (flags.stage === InspectStage.ARCHIVE) {
const vcs = getVcsClient();
await vcs.ensureRepoExistsAsync();
await vcs.makeShallowCopyAsync(tmpWorkingdir);
await vcsClient.ensureRepoExistsAsync();
await vcsClient.makeShallowCopyAsync(tmpWorkingdir);
await this.copyToOutputDirAsync(tmpWorkingdir, outputDirectory);
} else {
try {
await runBuildAndSubmitAsync(
graphqlClient,
analytics,
vcsClient,
projectDir,
{
nonInteractive: false,
@@ -37,6 +37,7 @@ export default class BuildInternal extends EasCommand {
...this.ContextOptions.DynamicProjectConfig,
...this.ContextOptions.ProjectDir,
...this.ContextOptions.Analytics,
...this.ContextOptions.Vcs,
};
async runAsync(): Promise<void> {
@@ -49,6 +50,7 @@ export default class BuildInternal extends EasCommand {
getDynamicPrivateProjectConfigAsync,
projectDir,
analytics,
vcsClient,
} = await this.getContextAsync(BuildInternal, {
nonInteractive: true,
});
@@ -60,6 +62,7 @@ export default class BuildInternal extends EasCommand {
await runBuildAndSubmitAsync(
graphqlClient,
analytics,
vcsClient,
projectDir,
{
requestedPlatform: flags.platform as RequestedPlatform,
@@ -56,6 +56,7 @@ export default class BuildList extends EasCommand {
static override contextDefinition = {
...this.ContextOptions.ProjectConfig,
...this.ContextOptions.LoggedIn,
...this.ContextOptions.Vcs,
};
async runAsync(): Promise<void> {
@@ -88,6 +88,7 @@ export default class BuildResign extends EasCommand {
...this.ContextOptions.DynamicProjectConfig,
...this.ContextOptions.ProjectDir,
...this.ContextOptions.Analytics,
...this.ContextOptions.Vcs,
};
async runAsync(): Promise<void> {
@@ -104,6 +105,7 @@ export default class BuildResign extends EasCommand {
getDynamicPrivateProjectConfigAsync,
projectDir,
analytics,
vcsClient,
} = await this.getContextAsync(BuildResign, {
nonInteractive: flags.nonInteractive,
});
@@ -145,6 +147,7 @@ export default class BuildResign extends EasCommand {
analytics,
env: buildProfile.env,
easJsonCliConfig,
vcsClient,
});
if (buildProfile.credentialsSource !== CredentialsSource.LOCAL && !nonInteractive) {
await credentialsCtx.appStore.ensureAuthenticatedAsync();
@@ -154,6 +157,7 @@ export default class BuildResign extends EasCommand {
projectDir,
nonInteractive,
exp,
vcsClient,
},
buildProfile
);
@@ -162,6 +166,7 @@ export default class BuildResign extends EasCommand {
exp,
xcodeBuildContext,
env: buildProfile.env,
vcsClient,
});
const credentialsResult = await ensureIosCredentialsForBuildResignAsync(
credentialsCtx,
@@ -199,8 +204,6 @@ export default class BuildResign extends EasCommand {
const buildResult = await waitForBuildEndAsync(graphqlClient, {
buildIds: [newBuild.id],
accountName: account.name,
nonInteractive,
projectDir,
});
if (!flags.json) {
printBuildResults(buildResult);
@@ -73,6 +73,7 @@ export default class Run extends EasCommand {
...this.ContextOptions.LoggedIn,
...this.ContextOptions.ProjectConfig,
...this.ContextOptions.ProjectDir,
...this.ContextOptions.Vcs,
};
async runAsync(): Promise<void> {
@@ -38,6 +38,7 @@ export default class BuildVersionGetView extends EasCommand {
...this.ContextOptions.LoggedIn,
...this.ContextOptions.DynamicProjectConfig,
...this.ContextOptions.ProjectDir,
...this.ContextOptions.Vcs,
};
public async runAsync(): Promise<void> {
@@ -49,6 +50,7 @@ export default class BuildVersionGetView extends EasCommand {
loggedIn: { graphqlClient },
getDynamicPrivateProjectConfigAsync,
projectDir,
vcsClient,
} = await this.getContextAsync(BuildVersionGetView, {
nonInteractive: true,
});
@@ -68,6 +70,7 @@ export default class BuildVersionGetView extends EasCommand {
easJsonAccessor,
platforms,
profileName: flags.profile ?? undefined,
projectDir,
});
const results: { [key in Platform]?: string } = {};
for (const { profile, platform } of buildProfiles) {
@@ -84,6 +87,7 @@ export default class BuildVersionGetView extends EasCommand {
exp,
buildProfile: profile,
platform,
vcsClient,
});
const remoteVersions = await AppVersionQuery.latestVersionAsync(
graphqlClient,
@@ -41,6 +41,7 @@ export default class BuildVersionSetView extends EasCommand {
...this.ContextOptions.LoggedIn,
...this.ContextOptions.DynamicProjectConfig,
...this.ContextOptions.ProjectDir,
...this.ContextOptions.Vcs,
};
public async runAsync(): Promise<void> {
@@ -49,6 +50,7 @@ export default class BuildVersionSetView extends EasCommand {
loggedIn: { graphqlClient },
getDynamicPrivateProjectConfigAsync,
projectDir,
vcsClient,
} = await this.getContextAsync(BuildVersionSetView, {
nonInteractive: false,
});
@@ -74,6 +76,7 @@ export default class BuildVersionSetView extends EasCommand {
exp,
buildProfile: profile,
platform,
vcsClient,
});
const remoteVersions = await AppVersionQuery.latestVersionAsync(
graphqlClient,
@@ -28,6 +28,7 @@ import {
} from '../../../project/remoteVersionSource';
import { resolveWorkflowAsync } from '../../../project/workflow';
import { getProfilesAsync } from '../../../utils/profiles';
import { Client } from '../../../vcs/vcs';
interface SyncContext<T extends Platform> {
projectDir: string;
@@ -35,6 +36,7 @@ interface SyncContext<T extends Platform> {
workflow: Workflow;
profile: BuildProfile<T>;
buildVersion: string;
vcsClient: Client;
}
export default class BuildVersionSyncView extends EasCommand {
@@ -58,6 +60,7 @@ export default class BuildVersionSyncView extends EasCommand {
...this.ContextOptions.LoggedIn,
...this.ContextOptions.DynamicProjectConfig,
...this.ContextOptions.ProjectDir,
...this.ContextOptions.Vcs,
};
public async runAsync(): Promise<void> {
@@ -66,6 +69,7 @@ export default class BuildVersionSyncView extends EasCommand {
loggedIn: { graphqlClient },
getDynamicPrivateProjectConfigAsync,
projectDir,
vcsClient,
} = await this.getContextAsync(BuildVersionSyncView, {
nonInteractive: true,
});
@@ -80,6 +84,7 @@ export default class BuildVersionSyncView extends EasCommand {
easJsonAccessor,
platforms,
profileName: flags.profile ?? undefined,
projectDir,
});
for (const profileInfo of buildProfiles) {
const { exp, projectId } = await getDynamicPrivateProjectConfigAsync({
@@ -96,6 +101,7 @@ export default class BuildVersionSyncView extends EasCommand {
exp,
buildProfile: profileInfo.profile,
platform: profileInfo.platform,
vcsClient,
});
const remoteVersions = await AppVersionQuery.latestVersionAsync(
graphqlClient,
@@ -103,7 +109,7 @@ export default class BuildVersionSyncView extends EasCommand {
toAppPlatform(profileInfo.platform),
applicationIdentifier
);
const workflow = await resolveWorkflowAsync(projectDir, profileInfo.platform);
const workflow = await resolveWorkflowAsync(projectDir, profileInfo.platform, vcsClient);
if (!remoteVersions?.buildVersion) {
Log.warn(
`Skipping versions sync for ${platformDisplayName}. There are no versions configured on Expo servers, use "eas build:version:set" or run a build to initialize it.`
@@ -127,6 +133,7 @@ export default class BuildVersionSyncView extends EasCommand {
profile: profileInfo.profile as BuildProfile<Platform.ANDROID>,
workflow,
buildVersion: remoteVersions.buildVersion,
vcsClient,
});
} else {
this.syncIosAsync({
@@ -135,6 +142,7 @@ export default class BuildVersionSyncView extends EasCommand {
profile: profileInfo.profile as BuildProfile<Platform.IOS>,
workflow,
buildVersion: remoteVersions.buildVersion,
vcsClient,
});
}
Log.withTick(
@@ -151,9 +159,10 @@ export default class BuildVersionSyncView extends EasCommand {
exp,
profile,
buildVersion,
vcsClient,
}: SyncContext<Platform.IOS>): Promise<void> {
const xcodeBuildContext = await resolveXcodeBuildContextAsync(
{ exp, projectDir, nonInteractive: false },
{ exp, projectDir, nonInteractive: false, vcsClient },
profile
);
const targets = await resolveTargetsAsync({
@@ -161,6 +170,7 @@ export default class BuildVersionSyncView extends EasCommand {
exp,
xcodeBuildContext,
env: profile.env,
vcsClient,
});
if (!isValidBuildNumber(buildVersion)) {
@@ -20,6 +20,7 @@ export default class BuildView extends EasCommand {
static override contextDefinition = {
...this.ContextOptions.ProjectConfig,
...this.ContextOptions.LoggedIn,
...this.ContextOptions.Vcs,
};
async runAsync(): Promise<void> {
@@ -1,16 +1,11 @@
import chalk from 'chalk';
import { createUpdateBranchOnAppAsync } from '../../branch/queries';
import { BranchNotFoundError } from '../../branch/utils';
import { createChannelOnAppAsync } from '../../channel/queries';
import { createAndLinkChannelAsync } from '../../channel/queries';
import EasCommand from '../../commandUtils/EasCommand';
import { EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
import { BranchQuery } from '../../graphql/queries/BranchQuery';
import Log from '../../log';
import { getDisplayNameForProjectIdAsync } from '../../project/projectUtils';
import { promptAsync } from '../../prompts';
import formatFields from '../../utils/formatFields';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
import { enableJsonOutput } from '../../utils/json';
export default class ChannelCreate extends EasCommand {
static override description = 'create a channel';
@@ -60,69 +55,13 @@ export default class ChannelCreate extends EasCommand {
}));
}
let branchId: string;
let branchMessage: string;
try {
const branch = await BranchQuery.getBranchByNameAsync(graphqlClient, {
appId: projectId,
name: channelName,
});
branchId = branch.id;
branchMessage = `We found a branch with the same name`;
} catch (error) {
if (error instanceof BranchNotFoundError) {
const newBranch = await createUpdateBranchOnAppAsync(graphqlClient, {
appId: projectId,
name: channelName,
});
branchId = newBranch.id;
branchMessage = `We also went ahead and made a branch with the same name`;
} else {
throw error;
}
}
const {
updateChannel: { createUpdateChannelForApp: newChannel },
} = await createChannelOnAppAsync(graphqlClient, {
await createAndLinkChannelAsync(graphqlClient, {
appId: projectId,
channelName,
branchId,
shouldPrintJson: jsonFlag,
});
if (!newChannel) {
throw new Error(
`Could not create channel with name ${channelName} on project with id ${projectId}`
);
}
if (jsonFlag) {
printJsonOnlyOutput(newChannel);
} else {
Log.addNewLineIfNone();
Log.withTick(
`Created a new channel on project ${chalk.bold(
await getDisplayNameForProjectIdAsync(graphqlClient, projectId)
)}`
);
Log.log(
formatFields([
{ label: 'Name', value: newChannel.name },
{ label: 'ID', value: newChannel.id },
])
);
Log.addNewLineIfNone();
Log.withTick(`${branchMessage} and have pointed the channel at it.`);
Log.log(
formatFields([
{ label: 'Name', value: newChannel.name },
{ label: 'ID', value: branchId },
])
);
Log.addNewLineIfNone();
Log.log(chalk.bold('You can now update your app by publishing!'));
}
Log.addNewLineIfNone();
Log.log(chalk.bold('You can now update your app by publishing!'));
}
}
@@ -4,7 +4,7 @@ import { print } from 'graphql';
import gql from 'graphql-tag';
import { selectBranchOnAppAsync } from '../../branch/queries';
import { hasStandardBranchMap } from '../../channel/branch-mapping';
import { hasEmptyBranchMap, hasStandardBranchMap } from '../../channel/branch-mapping';
import { selectChannelOnAppAsync } from '../../channel/queries';
import EasCommand from '../../commandUtils/EasCommand';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
@@ -102,7 +102,7 @@ export default class ChannelEdit extends EasCommand {
if (isRollout(existingChannel)) {
throw new Error('There is a rollout in progress. Manage it with "channel:rollout" instead.');
} else if (!hasStandardBranchMap(existingChannel)) {
} else if (!hasStandardBranchMap(existingChannel) && !hasEmptyBranchMap(existingChannel)) {
throw new Error('Only standard branch mappings can be edited with this command.');
}
@@ -17,11 +17,13 @@ import {
RolloutActions,
RolloutMainMenu,
} from '../../rollout/actions/RolloutMainMenu';
import { enableJsonOutput } from '../../utils/json';
enum ActionRawFlagValue {
CREATE = 'create',
EDIT = 'edit',
END = 'end',
VIEW = 'view',
}
type ChannelRolloutRawArgsAndFlags = {
channel?: string;
@@ -137,8 +139,7 @@ export default class ChannelRollout extends EasCommand {
nonInteractive: argsAndFlags.nonInteractive,
});
if (argsAndFlags.json) {
// TODO(quin): implement json output
throw new Error('Developer Preview doesnt support JSON output yet');
enableJsonOutput();
}
const app = { projectId, exp };
@@ -153,7 +154,7 @@ export default class ChannelRollout extends EasCommand {
} else {
Log.addNewLineIfNone();
Log.warn(
`✨ This command is in Developer Preview and has not been released to production yet`
`✨ This command is in Developer Preview and has not been released to production yet. Website support is coming soon.`
);
Log.addNewLineIfNone();
await new RolloutMainMenu(argsAndFlags).runAsync(ctx);
@@ -168,6 +169,8 @@ export default class ChannelRollout extends EasCommand {
return ManageRolloutActions.EDIT;
case ActionRawFlagValue.END:
return ManageRolloutActions.END;
case ActionRawFlagValue.VIEW:
return ManageRolloutActions.VIEW;
}
}
@@ -15,6 +15,7 @@ export default class Credentials extends EasCommand {
...this.ContextOptions.OptionalProjectConfig,
...this.ContextOptions.DynamicProjectConfig,
...this.ContextOptions.Analytics,
...this.ContextOptions.Vcs,
};
async runAsync(): Promise<void> {
@@ -24,6 +25,7 @@ export default class Credentials extends EasCommand {
privateProjectConfig,
getDynamicPrivateProjectConfigAsync,
analytics,
vcsClient,
} = await this.getContextAsync(Credentials, {
nonInteractive: false,
});
@@ -31,6 +33,7 @@ export default class Credentials extends EasCommand {
await new SelectPlatform(
actor,
graphqlClient,
vcsClient,
analytics,
privateProjectConfig ?? null,
getDynamicPrivateProjectConfigAsync,
+7 -5
View File
@@ -5,16 +5,18 @@ import EasCommand from '../commandUtils/EasCommand';
import Log from '../log';
import { resolveWorkflowAsync } from '../project/workflow';
import { easCliVersion } from '../utils/easCli';
import { Client } from '../vcs/vcs';
export default class Diagnostics extends EasCommand {
static override description = 'display environment info';
static override contextDefinition = {
...this.ContextOptions.ProjectDir,
...this.ContextOptions.Vcs,
};
async runAsync(): Promise<void> {
const { projectDir } = await this.getContextAsync(Diagnostics, {
const { projectDir, vcsClient } = await this.getContextAsync(Diagnostics, {
nonInteractive: true,
});
@@ -43,13 +45,13 @@ export default class Diagnostics extends EasCommand {
);
Log.log(info.trimEnd());
await this.printWorkflowAsync(projectDir);
await this.printWorkflowAsync(projectDir, vcsClient);
Log.newLine();
}
private async printWorkflowAsync(projectDir: string): Promise<void> {
const androidWorkflow = await resolveWorkflowAsync(projectDir, Platform.ANDROID);
const iosWorkflow = await resolveWorkflowAsync(projectDir, Platform.IOS);
private async printWorkflowAsync(projectDir: string, vcsClient: Client): Promise<void> {
const androidWorkflow = await resolveWorkflowAsync(projectDir, Platform.ANDROID, vcsClient);
const iosWorkflow = await resolveWorkflowAsync(projectDir, Platform.IOS, vcsClient);
if (androidWorkflow === iosWorkflow) {
Log.log(` Project workflow: ${androidWorkflow}`);
@@ -47,6 +47,7 @@ export default class MetadataLint extends EasCommand {
easJsonAccessor: EasJsonAccessor.fromProjectPath(projectDir),
platforms: [Platform.IOS],
profileName: flags.profile,
projectDir,
});
if (submitProfiles.length !== 1) {
@@ -27,6 +27,7 @@ export default class MetadataPull extends EasCommand {
...this.ContextOptions.ProjectConfig,
...this.ContextOptions.LoggedIn,
...this.ContextOptions.Analytics,
...this.ContextOptions.Vcs,
};
async runAsync(): Promise<void> {
@@ -37,18 +38,20 @@ export default class MetadataPull extends EasCommand {
loggedIn: { actor, graphqlClient },
privateProjectConfig: { exp, projectId, projectDir },
analytics,
vcsClient,
} = await this.getContextAsync(MetadataPull, {
nonInteractive: false,
});
// this command is interactive (all nonInteractive flags passed to utility functions are false)
await ensureProjectConfiguredAsync({ projectDir, nonInteractive: false });
await ensureProjectConfiguredAsync({ projectDir, nonInteractive: false, vcsClient });
const submitProfiles = await getProfilesAsync({
type: 'submit',
easJsonAccessor: EasJsonAccessor.fromProjectPath(projectDir),
platforms: [Platform.IOS],
profileName: flags.profile,
projectDir,
});
if (submitProfiles.length !== 1) {
@@ -63,6 +66,7 @@ export default class MetadataPull extends EasCommand {
graphqlClient,
analytics,
nonInteractive: false,
vcsClient,
});
try {
@@ -25,6 +25,7 @@ export default class MetadataPush extends EasCommand {
...this.ContextOptions.ProjectConfig,
...this.ContextOptions.LoggedIn,
...this.ContextOptions.Analytics,
...this.ContextOptions.Vcs,
};
async runAsync(): Promise<void> {
@@ -35,18 +36,20 @@ export default class MetadataPush extends EasCommand {
loggedIn: { actor, graphqlClient },
privateProjectConfig: { exp, projectId, projectDir },
analytics,
vcsClient,
} = await this.getContextAsync(MetadataPush, {
nonInteractive: false,
});
// this command is interactive (all nonInteractive flags passed to utility functions are false)
await ensureProjectConfiguredAsync({ projectDir, nonInteractive: false });
await ensureProjectConfiguredAsync({ projectDir, nonInteractive: false, vcsClient });
const submitProfiles = await getProfilesAsync({
type: 'submit',
easJsonAccessor: EasJsonAccessor.fromProjectPath(projectDir),
platforms: [Platform.IOS],
profileName: flags.profile,
projectDir,
});
if (submitProfiles.length !== 1) {
@@ -61,6 +64,7 @@ export default class MetadataPush extends EasCommand {
graphqlClient,
analytics,
nonInteractive: false,
vcsClient,
});
try {
+70 -15
View File
@@ -16,7 +16,7 @@ import { ora } from '../../ora';
import { createOrModifyExpoConfigAsync, getPrivateExpoConfig } from '../../project/expoConfig';
import { findProjectIdByAccountNameAndSlugNullableAsync } from '../../project/fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync';
import { toAppPrivacy } from '../../project/projectUtils';
import { confirmAsync, promptAsync } from '../../prompts';
import { Choice, confirmAsync, promptAsync } from '../../prompts';
import { Actor } from '../../user/User';
type InitializeMethodOptions = {
@@ -234,21 +234,11 @@ export default class ProjectInit extends EasCommand {
if (allAccounts.length === 1) {
accountName = allAccounts[0].name;
} else {
// if regular user, put primary account first
const sortedAccounts =
actor.__typename === 'Robot'
? allAccounts
: [...allAccounts].sort((a, _b) =>
actor.__typename === 'User' ? (a.name === actor.username ? -1 : 1) : 0
);
const choices = ProjectInit.getAccountChoices(
actor,
accountNamesWhereUserHasSufficientPermissionsToCreateApp
);
const choices = sortedAccounts.map(account => ({
title: account.name,
value: account,
description: !accountNamesWhereUserHasSufficientPermissionsToCreateApp.has(account.name)
? '(Viewer Role)'
: undefined,
}));
accountName = (
await promptAsync({
type: 'select',
@@ -321,6 +311,71 @@ export default class ProjectInit extends EasCommand {
return createdProjectId;
}
private static getAccountChoices(
actor: Actor,
namesWithSufficientPermissions: Set<string>
): Choice[] {
const allAccounts = actor.accounts;
const sortedAccounts =
actor.__typename === 'Robot'
? allAccounts
: [...allAccounts].sort((a, _b) =>
actor.__typename === 'User' ? (a.name === actor.username ? -1 : 1) : 0
);
if (actor.__typename !== 'Robot') {
const personalAccount = allAccounts?.find(
account => account?.ownerUserActor?.id === actor.id
);
const personalAccountChoice = personalAccount
? {
title: personalAccount.name,
value: personalAccount,
description: !namesWithSufficientPermissions.has(personalAccount.name)
? '(Personal) (Viewer Role)'
: '(Personal)',
}
: undefined;
const userAccounts = allAccounts
?.filter(account => account.ownerUserActor && account.name !== actor.username)
.map(account => ({
title: account.name,
value: account,
description: !namesWithSufficientPermissions.has(account.name)
? '(Team) (Viewer Role)'
: '(Team)',
}));
const organizationAccounts = allAccounts
?.filter(account => account.name !== actor.username && !account.ownerUserActor)
.map(account => ({
title: account.name,
value: account,
description: !namesWithSufficientPermissions.has(account.name)
? '(Organization) (Viewer Role)'
: '(Organization)',
}));
let choices: Choice[] = [];
if (personalAccountChoice) {
choices = [personalAccountChoice];
}
return [...choices, ...userAccounts, ...organizationAccounts].sort((a, _b) =>
actor.__typename === 'User' ? (a.value.name === actor.username ? -1 : 1) : 0
);
}
return sortedAccounts.map(account => ({
title: account.name,
value: account,
description: !namesWithSufficientPermissions.has(account.name) ? '(Viewer Role)' : undefined,
}));
}
async runAsync(): Promise<void> {
const {
flags: { id: idArgument, force, 'non-interactive': nonInteractive },
+4
View File
@@ -94,6 +94,7 @@ export default class Submit extends EasCommand {
...this.ContextOptions.ProjectConfig,
...this.ContextOptions.ProjectDir,
...this.ContextOptions.Analytics,
...this.ContextOptions.Vcs,
};
async runAsync(): Promise<void> {
@@ -102,6 +103,7 @@ export default class Submit extends EasCommand {
loggedIn: { actor, graphqlClient },
privateProjectConfig: { exp, projectId, projectDir },
analytics,
vcsClient,
} = await this.getContextAsync(Submit, {
nonInteractive: false,
});
@@ -118,6 +120,7 @@ export default class Submit extends EasCommand {
easJsonAccessor: EasJsonAccessor.fromProjectPath(projectDir),
platforms,
profileName: flagsWithPlatform.profile,
projectDir,
});
const submissions: SubmissionFragment[] = [];
@@ -134,6 +137,7 @@ export default class Submit extends EasCommand {
analytics,
exp,
projectId,
vcsClient,
});
if (submissionProfiles.length > 1) {
@@ -3,10 +3,12 @@ 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',
@@ -19,6 +21,7 @@ describe(ensureEASUpdateIsConfiguredAsync, () => {
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.`
@@ -57,12 +57,6 @@ jest.mock('../../../fetch');
describe(UpdateRepublish.name, () => {
afterEach(() => vol.reset());
it('errors without --channel, --branch, or --group', async () => {
await expect(new UpdateRepublish([], commandOptions).run()).rejects.toThrow(
'--channel, --branch, or --group must be specified'
);
});
it('errors when providing both --group and --branch', async () => {
const flags = ['--group=1234', '--branch=main'];
@@ -43,6 +43,10 @@ jest.mock('@expo/config');
jest.mock('@expo/config-plugins');
jest.mock('../../../branch/queries');
jest.mock('../../../commandUtils/context/contextUtils/getProjectIdAsync');
jest.mock('../../../project/projectUtils', () => ({
...jest.requireActual('../../../project/projectUtils'),
enforceRollBackToEmbeddedUpdateSupportAsync: jest.fn(),
}));
jest.mock('../../../update/configure');
jest.mock('../../../update/getBranchNameFromChannelNameAsync');
jest.mock('../../../graphql/mutations/PublishMutation');
@@ -10,7 +10,6 @@ import {
ensureEASUpdateIsConfiguredAsync,
ensureEASUpdateIsConfiguredInEasJsonAsync,
} from '../../update/configure';
import { getVcsClient } from '../../vcs';
export default class UpdateConfigure extends EasCommand {
static override description = 'configure the project to support EAS Update';
@@ -28,6 +27,7 @@ export default class UpdateConfigure extends EasCommand {
static override contextDefinition = {
...this.ContextOptions.ProjectConfig,
...this.ContextOptions.LoggedIn,
...this.ContextOptions.Vcs,
};
async runAsync(): Promise<void> {
@@ -36,6 +36,7 @@ export default class UpdateConfigure extends EasCommand {
const {
privateProjectConfig: { projectId, exp, projectDir },
loggedIn: { graphqlClient },
vcsClient,
} = await this.getContextAsync(UpdateConfigure, {
nonInteractive: flags['non-interactive'],
});
@@ -44,13 +45,14 @@ export default class UpdateConfigure extends EasCommand {
'💡 The following process will configure your project to use EAS Update. These changes only apply to your local project files and you can safely revert them at any time.'
);
await getVcsClient().ensureRepoExistsAsync();
await vcsClient.ensureRepoExistsAsync();
await ensureEASUpdateIsConfiguredAsync(graphqlClient, {
exp,
projectId,
projectDir,
platform,
vcsClient,
});
await ensureEASUpdateIsConfiguredInEasJsonAsync(projectDir);
+52 -15
View File
@@ -35,6 +35,7 @@ import {
getRuntimeVersionObjectAsync,
getUpdateMessageForCommandAsync,
isUploadedAssetCountAboveWarningThreshold,
platformDisplayNames,
resolveInputDirectoryAsync,
uploadAssetsAsync,
} from '../../project/publish';
@@ -51,10 +52,10 @@ import uniqBy from '../../utils/expodash/uniqBy';
import formatFields from '../../utils/formatFields';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
import { maybeWarnAboutEasOutagesAsync } from '../../utils/statuspageService';
import { getVcsClient } from '../../vcs';
type RawUpdateFlags = {
auto: boolean;
dev: boolean;
branch?: string;
channel?: string;
message?: string;
@@ -73,6 +74,7 @@ type RawUpdateFlags = {
type UpdateFlags = {
auto: boolean;
dev: boolean;
platform: ExpoCLIExportPlatformFlag;
branchName?: string;
channelName?: string;
@@ -133,6 +135,10 @@ export default class UpdatePublish extends EasCommand {
default: 'all',
required: false,
}),
dev: Flags.boolean({
description: 'Publish a development bundle',
default: false,
}),
auto: Flags.boolean({
description:
'Use the current git branch and commit message for the EAS branch and update message',
@@ -148,6 +154,7 @@ export default class UpdatePublish extends EasCommand {
static override contextDefinition = {
...this.ContextOptions.DynamicProjectConfig,
...this.ContextOptions.LoggedIn,
...this.ContextOptions.Vcs,
};
async runAsync(): Promise<void> {
@@ -157,6 +164,7 @@ export default class UpdatePublish extends EasCommand {
auto: autoFlag,
platform: platformFlag,
channelName: channelNameArg,
dev,
updateMessage: updateMessageArg,
inputDir,
skipBundler,
@@ -171,6 +179,7 @@ export default class UpdatePublish extends EasCommand {
getDynamicPublicProjectConfigAsync,
getDynamicPrivateProjectConfigAsync,
loggedIn: { graphqlClient },
vcsClient,
} = await this.getContextAsync(UpdatePublish, {
nonInteractive,
});
@@ -192,6 +201,7 @@ export default class UpdatePublish extends EasCommand {
platform: getRequestedPlatform(platformFlag),
projectDir,
projectId,
vcsClient,
});
const { exp } = await getDynamicPublicProjectConfigAsync();
@@ -200,6 +210,7 @@ export default class UpdatePublish extends EasCommand {
const branchName = await getBranchNameForCommandAsync({
graphqlClient,
vcsClient,
projectId,
channelNameArg,
branchNameArg,
@@ -208,7 +219,7 @@ export default class UpdatePublish extends EasCommand {
paginatedQueryOptions,
});
const updateMessage = await getUpdateMessageForCommandAsync({
const updateMessage = await getUpdateMessageForCommandAsync(vcsClient, {
updateMessageArg,
autoFlag,
nonInteractive,
@@ -219,7 +230,7 @@ export default class UpdatePublish extends EasCommand {
if (!skipBundler) {
const bundleSpinner = ora().start('Exporting...');
try {
await buildBundlesAsync({ projectDir, inputDir, exp, platformFlag, clearCache });
await buildBundlesAsync({ projectDir, inputDir, dev, exp, platformFlag, clearCache });
bundleSpinner.succeed('Exported bundle(s)');
} catch (e) {
bundleSpinner.fail('Export failed');
@@ -242,20 +253,22 @@ export default class UpdatePublish extends EasCommand {
realizedPlatforms = Object.keys(assets) as PublishPlatform[];
// Timeout mechanism:
// - Start with 60 second timeout. 60 seconds is chosen because the cloud function that processes
// uploaded assets has a timeout of 60 seconds.
// - Each time one or more assets reports as ready, reset the timeout to 60 seconds.
// - Start upload. Internally, uploadAssetsAsync uploads them all and then checks for successful
// - Start with NO_ACTIVITY_TIMEOUT. 90 seconds is chosen because the cloud function that processes
// uploaded assets has a timeout of 60 seconds and uploading can take some time on a slow connection.
// - Each time one or more assets reports as ready, reset the timeout.
// - Each time an asset upload begins, reset the timeout. This includes retries.
// - Start upload. Internally, uploadAssetsAsync uploads them all first and then checks for successful
// processing every (5 + n) seconds with a linear backoff of n + 1 second.
// - At the same time as upload is started, start timeout checker which checks every 1 second to see
// if timeout has been reached. When timeout expires, send a cancellation signal to currently running
// upload function call to instruct it to stop uploading or checking for successful processing.
const NO_ACTIVITY_TIMEOUT = 90 * 1000; // 90 seconds
let lastUploadedStorageKeys = new Set<string>();
let lastAssetUploadResults: {
asset: RawAsset & { storageKey: string };
finished: boolean;
}[] = [];
let timeAtWhichToTimeout = Date.now() + 60 * 1000; // sixty seconds from now
let timeAtWhichToTimeout = Date.now() + NO_ACTIVITY_TIMEOUT;
const cancelationToken = { isCanceledOrFinished: false };
const uploadResults = await Promise.race([
@@ -269,7 +282,7 @@ export default class UpdatePublish extends EasCommand {
assetUploadResults.filter(r => r.finished).map(r => r.asset.storageKey)
);
if (!areSetsEqual(currentUploadedStorageKeys, lastUploadedStorageKeys)) {
timeAtWhichToTimeout = Date.now() + 60 * 1000; // reset timeout to sixty seconds from now
timeAtWhichToTimeout = Date.now() + NO_ACTIVITY_TIMEOUT; // reset timeout to NO_ACTIVITY_TIMEOUT
lastUploadedStorageKeys = currentUploadedStorageKeys;
lastAssetUploadResults = assetUploadResults;
}
@@ -277,6 +290,10 @@ export default class UpdatePublish extends EasCommand {
const totalAssets = assetUploadResults.length;
const missingAssetCount = assetUploadResults.filter(a => !a.finished).length;
assetSpinner.text = `Uploading (${totalAssets - missingAssetCount}/${totalAssets})`;
},
() => {
// when an upload is retried, reset the timeout as we know this will now need more time
timeAtWhichToTimeout = Date.now() + NO_ACTIVITY_TIMEOUT; // reset timeout to NO_ACTIVITY_TIMEOUT
}
),
(async () => {
@@ -325,12 +342,32 @@ export default class UpdatePublish extends EasCommand {
for (const uploadedAssetPath of uploadResults.uniqueUploadedAssetPaths) {
Log.debug(chalk.dim(`- ${uploadedAssetPath}`));
}
const platformString = (Object.keys(assets) as PublishPlatform[])
.map(platform => {
const collectedAssetForPlatform = nullthrows(assets[platform]);
const totalAssetsForPlatform = collectedAssetForPlatform.assets.length + 1; // launch asset
const assetString = totalAssetsForPlatform === 1 ? 'asset' : 'assets';
return `${totalAssetsForPlatform} ${platformDisplayNames[platform]} ${assetString}`;
})
.join(', ');
Log.withInfo(
`${platformString} (maximum: ${assetLimitPerUpdateGroup} total per update). ${learnMore(
'https://expo.fyi/eas-update-asset-limits',
{ learnMoreMessage: 'Learn more about asset limits.' }
)}`
);
} catch (e) {
assetSpinner.fail('Failed to upload');
throw e;
}
const runtimeVersions = await getRuntimeVersionObjectAsync(exp, realizedPlatforms, projectDir);
const runtimeVersions = await getRuntimeVersionObjectAsync(
exp,
realizedPlatforms,
projectDir,
vcsClient
);
const runtimeToPlatformMapping =
getRuntimeToPlatformMappingFromRuntimeVersions(runtimeVersions);
@@ -344,12 +381,11 @@ export default class UpdatePublish extends EasCommand {
branchId,
channelName: branchName,
});
Log.withTick(
`Channel: ${chalk.bold(branchName)} pointed at branch: ${chalk.bold(branchName)}`
);
}
Log.withTick(`Channel: ${chalk.bold(branchName)} pointed at branch: ${chalk.bold(branchName)}`);
const vcsClient = getVcsClient();
const gitCommitHash = await vcsClient.getCommitHashAsync();
const isGitWorkingTreeDirty = await vcsClient.hasUncommittedChangesAsync();
@@ -507,7 +543,7 @@ export default class UpdatePublish extends EasCommand {
private sanitizeFlags(flags: RawUpdateFlags): UpdateFlags {
const nonInteractive = flags['non-interactive'] ?? false;
const { auto, branch: branchName, channel: channelName, message: updateMessage } = flags;
const { auto, branch: branchName, channel: channelName, dev, message: updateMessage } = flags;
if (nonInteractive && !auto && !(updateMessage && (branchName || channelName))) {
Errors.error(
'--branch and --message, or --channel and --message are required when updating in non-interactive mode unless --auto is specified',
@@ -536,6 +572,7 @@ export default class UpdatePublish extends EasCommand {
auto,
branchName,
channelName,
dev,
updateMessage,
inputDir: flags['input-dir'],
skipBundler: flags['skip-bundler'],
@@ -1,6 +1,8 @@
import { Platform } from '@expo/config';
import { Flags } from '@oclif/core';
import { selectBranchOnAppAsync } from '../../branch/queries';
import { selectChannelOnAppAsync } from '../../channel/queries';
import EasCommand from '../../commandUtils/EasCommand';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
@@ -151,9 +153,6 @@ export default class UpdateRepublish extends EasCommand {
if (nonInteractive && !groupId) {
throw new Error('Only --group can be used in non-interactive mode');
}
if (!groupId && !(branchName || channelName)) {
throw new Error(`--channel, --branch, or --group must be specified`);
}
const platform =
rawFlags.platform === 'all' ? defaultRepublishPlatforms : ([rawFlags.platform] as Platform[]);
@@ -190,6 +189,10 @@ async function getOrAskUpdatesAsync(
}));
}
if (flags.nonInteractive) {
throw new Error('Must supply --group when in non-interactive mode');
}
if (flags.branchName) {
return await askUpdatesFromBranchNameAsync(graphqlClient, {
...flags,
@@ -206,7 +209,55 @@ async function getOrAskUpdatesAsync(
});
}
throw new Error('--channel, --branch, or --group is required');
const { choice } = await promptAsync({
type: 'select',
message: 'Find update by branch or channel?',
name: 'choice',
choices: [
{ title: 'Branch', value: 'branch' },
{ title: 'Channel', value: 'channel' },
],
});
if (choice === 'channel') {
const { name } = await selectChannelOnAppAsync(graphqlClient, {
projectId,
selectionPromptTitle: 'Select a channel to view',
paginatedQueryOptions: {
json: flags.json,
nonInteractive: flags.nonInteractive,
offset: 0,
},
});
return await askUpdatesFromChannelNameAsync(graphqlClient, {
...flags,
channelName: name,
projectId,
});
} else if (choice === 'branch') {
const { name } = await selectBranchOnAppAsync(graphqlClient, {
projectId,
promptTitle: 'Select branch from which to choose update',
displayTextForListItem: updateBranch => ({
title: updateBranch.name,
}),
// discard limit and offset because this query is not their intended target
paginatedQueryOptions: {
json: flags.json,
nonInteractive: flags.nonInteractive,
offset: 0,
},
});
return await askUpdatesFromBranchNameAsync(graphqlClient, {
...flags,
branchName: name,
projectId,
});
} else {
throw new Error('Must choose update via channel or branch');
}
}
/** Ask the user which update needs to be republished by branch name, this requires interactive mode */
@@ -219,10 +270,6 @@ async function askUpdatesFromBranchNameAsync(
nonInteractive,
}: { projectId: string; branchName: string; json: boolean; nonInteractive: boolean }
): Promise<UpdateToRepublish[]> {
if (nonInteractive) {
throw new Error('Must supply --group when in non-interactive mode');
}
const updateGroup = await selectUpdateGroupOnBranchAsync(graphqlClient, {
projectId,
branchName,
@@ -246,10 +293,6 @@ async function askUpdatesFromChannelNameAsync(
nonInteractive,
}: { projectId: string; channelName: string; json: boolean; nonInteractive: boolean }
): Promise<UpdateToRepublish[]> {
if (nonInteractive) {
throw new Error('Must supply --group when in non-interactive mode');
}
const branchName = await getBranchNameFromChannelNameAsync(graphqlClient, projectId, channelName);
return await askUpdatesFromBranchNameAsync(graphqlClient, {
@@ -20,7 +20,10 @@ import { PublishMutation } from '../../graphql/mutations/PublishMutation';
import Log, { link } from '../../log';
import { ora } from '../../ora';
import { RequestedPlatform } from '../../platform';
import { getOwnerAccountForProjectIdAsync } from '../../project/projectUtils';
import {
enforceRollBackToEmbeddedUpdateSupportAsync,
getOwnerAccountForProjectIdAsync,
} from '../../project/projectUtils';
import {
ExpoCLIExportPlatformFlag,
defaultPublishPlatforms,
@@ -43,7 +46,6 @@ import uniqBy from '../../utils/expodash/uniqBy';
import formatFields from '../../utils/formatFields';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
import { maybeWarnAboutEasOutagesAsync } from '../../utils/statuspageService';
import { getVcsClient } from '../../vcs';
type RawUpdateFlags = {
auto: boolean;
@@ -68,7 +70,6 @@ type UpdateFlags = {
};
export default class UpdateRollBackToEmbedded extends EasCommand {
static override hidden = true; // until we launch
static override description = 'roll back to the embedded update';
static override flags = {
@@ -86,7 +87,11 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
}),
platform: Flags.enum({
char: 'p',
options: [...defaultPublishPlatforms, 'all'],
options: [
// TODO: Add web when it's fully supported
...defaultPublishPlatforms,
'all',
],
default: 'all',
required: false,
}),
@@ -105,6 +110,7 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
static override contextDefinition = {
...this.ContextOptions.DynamicProjectConfig,
...this.ContextOptions.LoggedIn,
...this.ContextOptions.Vcs,
};
async runAsync(): Promise<void> {
@@ -125,6 +131,7 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
getDynamicPublicProjectConfigAsync,
getDynamicPrivateProjectConfigAsync,
loggedIn: { graphqlClient },
vcsClient,
} = await this.getContextAsync(UpdateRollBackToEmbedded, {
nonInteractive,
});
@@ -146,14 +153,19 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
platform: getRequestedPlatform(platformFlag),
projectDir,
projectId,
vcsClient,
});
// check that the expo-updates package version supports roll back to embedded
await enforceRollBackToEmbeddedUpdateSupportAsync(projectDir);
const { exp } = await getDynamicPublicProjectConfigAsync();
const { exp: expPrivate } = await getDynamicPrivateProjectConfigAsync();
const codeSigningInfo = await getCodeSigningInfoAsync(expPrivate, privateKeyPath);
const branchName = await getBranchNameForCommandAsync({
graphqlClient,
vcsClient,
projectId,
channelNameArg,
branchNameArg,
@@ -162,7 +174,7 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
paginatedQueryOptions,
});
const updateMessage = await getUpdateMessageForCommandAsync({
const updateMessage = await getUpdateMessageForCommandAsync(vcsClient, {
updateMessageArg,
autoFlag,
nonInteractive,
@@ -186,12 +198,15 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
Log.withTick(`Channel: ${chalk.bold(branchName)} pointed at branch: ${chalk.bold(branchName)}`);
const vcsClient = getVcsClient();
const gitCommitHash = await vcsClient.getCommitHashAsync();
const isGitWorkingTreeDirty = await vcsClient.hasUncommittedChangesAsync();
const runtimeVersions = await getRuntimeVersionObjectAsync(exp, realizedPlatforms, projectDir);
const runtimeVersions = await getRuntimeVersionObjectAsync(
exp,
realizedPlatforms,
projectDir,
vcsClient
);
let newUpdates: UpdatePublishMutation['updateBranch']['publishUpdateGroups'];
const publishSpinner = ora('Publishing...').start();
@@ -0,0 +1,40 @@
import { Flags } from '@oclif/core';
import EasCommand from '../../commandUtils/EasCommand';
import { promptAsync } from '../../prompts';
import UpdateRepublish from './republish';
import UpdateRollBackToEmbedded from './roll-back-to-embedded';
export default class UpdateRollback extends EasCommand {
static override description = 'roll back to an embedded update or an existing update';
static override flags = {
'private-key-path': Flags.string({
description: `File containing the PEM-encoded private key corresponding to the certificate in expo-updates' configuration. Defaults to a file named "private-key.pem" in the certificate's directory.`,
required: false,
}),
};
async runAsync(): Promise<void> {
const { flags } = await this.parse(UpdateRollback);
const { choice } = await promptAsync({
type: 'select',
message: 'Which type of update would you like to roll back to?',
name: 'choice',
choices: [
{ title: 'Published Update', value: 'published' },
{ title: 'Embedded Update', value: 'embedded' },
],
});
const privateKeyPathArg = flags['private-key-path']
? ['--private-key-path', flags['private-key-path']]
: [];
if (choice === 'published') {
await UpdateRepublish.run(privateKeyPathArg);
} else {
await UpdateRollBackToEmbedded.run(privateKeyPathArg);
}
}
}
@@ -11,6 +11,7 @@ import {
} from '../../../project/projectUtils';
import { promptAsync } from '../../../prompts';
import { CredentialsContext } from '../../context';
import { AndroidPackageNotDefinedError } from '../../errors';
import { AppLookupParams } from '../api/GraphqlClient';
/**
@@ -108,10 +109,11 @@ export async function getAppLookupParamsFromContextAsync(
const androidApplicationIdentifier = await getApplicationIdAsync(
ctx.projectDir,
ctx.exp,
ctx.vcsClient,
gradleContext
);
if (!androidApplicationIdentifier) {
throw new Error(
throw new AndroidPackageNotDefinedError(
`android.package needs to be defined in your ${getProjectConfigDescription(
ctx.projectDir
)} file`
@@ -260,7 +260,6 @@ export async function createKeystoreAsync(
keystorePassword: keystore.keystorePassword,
keyAlias: keystore.keyAlias,
keyPassword: keystore.keyPassword,
type: keystore.type,
},
account.id
);
@@ -9,6 +9,7 @@ import Log from '../log';
import { getPrivateExpoConfig } from '../project/expoConfig';
import { confirmAsync } from '../prompts';
import { Actor } from '../user/User';
import { Client } from '../vcs/vcs';
import * as AndroidGraphqlClient from './android/api/GraphqlClient';
import * as IosGraphqlClient from './ios/api/GraphqlClient';
import AppStoreApi from './ios/appstore/AppStoreApi';
@@ -28,6 +29,7 @@ export class CredentialsContext {
public readonly user: Actor;
public readonly graphqlClient: ExpoGraphqlClient;
public readonly analytics: Analytics;
public readonly vcsClient: Client;
public readonly easJsonCliConfig?: EasJson['cli'];
private shouldAskAuthenticateAppStore: boolean = true;
@@ -44,6 +46,7 @@ export class CredentialsContext {
user: Actor;
graphqlClient: ExpoGraphqlClient;
analytics: Analytics;
vcsClient: Client;
env?: Env;
}
) {
@@ -52,6 +55,7 @@ export class CredentialsContext {
this.user = options.user;
this.graphqlClient = options.graphqlClient;
this.analytics = options.analytics;
this.vcsClient = options.vcsClient;
this.nonInteractive = options.nonInteractive ?? false;
this.projectInfo = options.projectInfo;
}
@@ -6,8 +6,8 @@ import { AndroidAppBuildCredentialsFragment, IosDistributionType } from '../../g
import Log from '../../log';
import { findApplicationTarget, findTargetByName } from '../../project/ios/target';
import zipObject from '../../utils/expodash/zipObject';
import { getVcsClient } from '../../vcs';
import GitClient from '../../vcs/clients/git';
import { Client } from '../../vcs/vcs';
import { CredentialsContext } from '../context';
import { App, Target, TargetCredentials } from '../ios/types';
import { readRawAsync } from './read';
@@ -38,7 +38,7 @@ export async function updateAndroidCredentialsAsync(
rawCredentialsJson?.android?.keystore?.keystorePath ?? 'credentials/android/keystore.jks';
Log.log(`Writing Keystore to ${keystorePath}`);
await updateFileAsync(ctx.projectDir, keystorePath, keystore.keystore);
const shouldWarnKeystore = await isFileUntrackedAsync(keystorePath);
const shouldWarnKeystore = await isFileUntrackedAsync(keystorePath, ctx.vcsClient);
const androidCredentials: Partial<CredentialsJson['android']> = {
keystore: {
@@ -52,7 +52,7 @@ export async function updateAndroidCredentialsAsync(
await fs.writeJson(getCredentialsJsonPath(ctx.projectDir), rawCredentialsJson, {
spaces: 2,
});
const shouldWarnCredentialsJson = await isFileUntrackedAsync('credentials.json');
const shouldWarnCredentialsJson = await isFileUntrackedAsync('credentials.json', ctx.vcsClient);
const newFilePaths = [];
if (shouldWarnKeystore) {
@@ -137,14 +137,14 @@ export async function updateIosCredentialsAsync(
const newFilePaths = [];
for (const [, targetCredentials] of Object.entries(iosCredentials)) {
if (await isFileUntrackedAsync(targetCredentials.distributionCertificate.path)) {
if (await isFileUntrackedAsync(targetCredentials.distributionCertificate.path, ctx.vcsClient)) {
newFilePaths.push(targetCredentials.distributionCertificate.path);
}
if (await isFileUntrackedAsync(targetCredentials.provisioningProfilePath)) {
if (await isFileUntrackedAsync(targetCredentials.provisioningProfilePath, ctx.vcsClient)) {
newFilePaths.push(targetCredentials.provisioningProfilePath);
}
}
if (await isFileUntrackedAsync('credentials.json')) {
if (await isFileUntrackedAsync('credentials.json', ctx.vcsClient)) {
newFilePaths.push('credentials.json');
}
displayUntrackedFilesWarning(newFilePaths);
@@ -296,8 +296,7 @@ async function updateFileAsync(
}
}
async function isFileUntrackedAsync(path: string): Promise<boolean> {
const vcsClient = getVcsClient();
async function isFileUntrackedAsync(path: string, vcsClient: Client): Promise<boolean> {
if (vcsClient instanceof GitClient) {
return await vcsClient.isFileUntrackedAsync(path);
}
@@ -15,3 +15,9 @@ export class UnsupportedCredentialsChoiceError extends Error {
super(message);
}
}
export class AndroidPackageNotDefinedError extends Error {
constructor(message?: string) {
super(message ?? 'android.package needs to be defined in your app.json/app.config.js file');
}
}
@@ -31,7 +31,7 @@ export function formatDeviceLabel(device: AppleDeviceFragment): string {
const deviceDetails = formatDeviceDetails(device);
return `${device.identifier}${deviceDetails !== '' ? ` ${deviceDetails}` : ''}${
device.name ? ` (${device.name})` : ''
}`;
}${device.createdAt ? ` (created at: ${device.createdAt})` : ''}`;
}
function formatDeviceDetails(device: AppleDeviceFragment): string {
@@ -177,7 +177,23 @@ export class SetUpAdhocProvisioningProfile {
);
}
// 6. Create (or update) app build credentials
// 6. Compare selected devices with the ones actually provisioned
const diffList = differenceBy(
chosenDevices,
appleProvisioningProfile.appleDevices,
'identifier'
);
if (diffList && diffList.length > 0) {
Log.warn(`Failed to provision ${diffList.length} of the selected devices:`);
for (const missingDevice of diffList) {
Log.warn(`- ${formatDeviceLabel(missingDevice)}`);
}
Log.log(
'Most commonly devices fail to to be provisioned while they are still being processed by Apple, which can take up to 24-72 hours. Check your Apple Developer Portal page at https://developer.apple.com/account/resources/devices/list, the devices in "Processing" status cannot be provisioned yet'
);
}
// 7. Create (or update) app build credentials
assert(appleProvisioningProfile);
return await assignBuildCredentialsAsync(
ctx,
@@ -0,0 +1,25 @@
import { v4 as uuidv4 } from 'uuid';
import { AppleDeviceClass, AppleDeviceFragment } from '../../../../graphql/generated';
import { formatDeviceLabel } from '../DeviceUtils';
describe(formatDeviceLabel, () => {
it('returns createdAt clause', async () => {
const currentDate = new Date();
const appleDevice = {
__typename: 'AppleDevice',
id: uuidv4(),
identifier: 'test-apple-device-id',
name: 'test-apple-device-name',
model: '15',
deviceClass: AppleDeviceClass.Iphone,
createdAt: currentDate.toISOString(),
} as AppleDeviceFragment;
const result = formatDeviceLabel(appleDevice);
expect(result).toEqual(
`test-apple-device-id (iPhone 15) (test-apple-device-name) (created at: ${currentDate.toISOString()})`
);
});
});
@@ -1,4 +1,39 @@
import { doUDIDsMatch } from '../SetUpAdhocProvisioningProfile';
import { Env } from '@expo/eas-build-job';
import { EasJson } from '@expo/eas-json';
import { Analytics } from '../../../../analytics/AnalyticsManager';
import { ExpoGraphqlClient } from '../../../../commandUtils/context/contextUtils/createGraphqlClient';
import {
Account,
AppleAppIdentifierFragment,
AppleDevice,
AppleDeviceClass,
AppleDeviceFragment,
AppleDistributionCertificateFragment,
IosAppBuildCredentialsFragment,
} from '../../../../graphql/generated';
import Log from '../../../../log';
import { getApplePlatformFromTarget } from '../../../../project/ios/target';
import { Actor } from '../../../../user/User';
import { Client } from '../../../../vcs/vcs';
import { CredentialsContext, CredentialsContextProjectInfo } from '../../../context';
import { ProvisioningProfile } from '../../appstore/Credentials.types';
import { ApplePlatform } from '../../appstore/constants';
import { assignBuildCredentialsAsync, getBuildCredentialsAsync } from '../BuildCredentialsUtils';
import { chooseDevicesAsync } from '../DeviceUtils';
import { SetUpAdhocProvisioningProfile, doUDIDsMatch } from '../SetUpAdhocProvisioningProfile';
jest.mock('../BuildCredentialsUtils');
jest.mock('../../../context');
jest.mock('../../../ios/api/GraphqlClient');
jest.mock('../DeviceUtils', () => {
return {
__esModule: true,
chooseDevicesAsync: jest.fn(),
formatDeviceLabel: jest.requireActual('../DeviceUtils').formatDeviceLabel,
};
});
jest.mock('../../../../project/ios/target');
describe(doUDIDsMatch, () => {
it('return false if UDIDs do not match', () => {
@@ -12,3 +47,105 @@ describe(doUDIDsMatch, () => {
expect(doUDIDsMatch(udidsA, udidsB)).toBe(true);
});
});
describe('runWithDistributionCertificateAsync', () => {
beforeEach(() => {
jest.resetAllMocks();
});
const setUpAdhocProvisioningProfile = new SetUpAdhocProvisioningProfile({
app: { account: {} as Account, projectName: 'projName', bundleIdentifier: 'bundleId' },
target: { targetName: 'targetName', bundleIdentifier: 'bundleId', entitlements: {} },
});
describe('compare chosen and provisioned devices', () => {
describe('not all devices provisioned', () => {
it('displays warning to the user and lists the missing devices', async () => {
const { ctx, distCert } = setUpTest();
jest.mocked(getBuildCredentialsAsync).mockResolvedValue({
provisioningProfile: {
appleTeam: {},
appleDevices: [{ identifier: 'id1' }],
developerPortalIdentifier: 'provisioningProfileId',
},
} as IosAppBuildCredentialsFragment);
const LogWarnSpy = jest.spyOn(Log, 'warn');
const LogLogSpy = jest.spyOn(Log, 'log');
const result = await setUpAdhocProvisioningProfile.runWithDistributionCertificateAsync(
ctx,
distCert
);
expect(result).toEqual({} as IosAppBuildCredentialsFragment);
expect(LogWarnSpy).toHaveBeenCalledTimes(3);
expect(LogWarnSpy).toHaveBeenCalledWith('Failed to provision 2 of the selected devices:');
expect(LogWarnSpy).toHaveBeenCalledWith('- id2 (iPhone) (Device 2)');
expect(LogWarnSpy).toHaveBeenCalledWith('- id3 (Mac) (Device 3)');
expect(LogLogSpy).toHaveBeenCalledTimes(1);
expect(LogLogSpy).toHaveBeenCalledWith(
'Most commonly devices fail to to be provisioned while they are still being processed by Apple, which can take up to 24-72 hours. Check your Apple Developer Portal page at https://developer.apple.com/account/resources/devices/list, the devices in "Processing" status cannot be provisioned yet'
);
});
});
describe('all devices provisioned', () => {
it('does not display warning', async () => {
const { ctx, distCert } = setUpTest();
jest.mocked(getBuildCredentialsAsync).mockResolvedValue({
provisioningProfile: {
appleTeam: {},
appleDevices: [{ identifier: 'id1' }, { identifier: 'id2' }, { identifier: 'id3' }],
developerPortalIdentifier: 'provisioningProfileId',
},
} as IosAppBuildCredentialsFragment);
const LogWarnSpy = jest.spyOn(Log, 'warn');
const LogLogSpy = jest.spyOn(Log, 'log');
const result = await setUpAdhocProvisioningProfile.runWithDistributionCertificateAsync(
ctx,
distCert
);
expect(result).toEqual({} as IosAppBuildCredentialsFragment);
expect(LogWarnSpy).not.toHaveBeenCalled();
expect(LogLogSpy).not.toHaveBeenCalled();
});
});
});
});
function setUpTest(): { ctx: CredentialsContext; distCert: AppleDistributionCertificateFragment } {
const ctx = jest.mocked(
new CredentialsContext(
{} as {
projectInfo: CredentialsContextProjectInfo | null;
easJsonCliConfig?: EasJson['cli'];
nonInteractive: boolean;
projectDir: string;
user: Actor;
graphqlClient: ExpoGraphqlClient;
analytics: Analytics;
env?: Env;
vcsClient: Client;
}
)
);
Object.defineProperty(ctx, 'ios', { value: jest.mock('../../../ios/api/GraphqlClient') });
ctx.ios.getDevicesForAppleTeamAsync = jest
.fn()
.mockResolvedValue([
{ identifier: 'id1' },
{ identifier: 'id2' },
{ identifier: 'id3' },
] as AppleDeviceFragment[]);
jest.mocked(chooseDevicesAsync).mockResolvedValue([
{ identifier: 'id1', name: 'Device 1', deviceClass: AppleDeviceClass.Ipad },
{ identifier: 'id2', name: 'Device 2', deviceClass: AppleDeviceClass.Iphone },
{ identifier: 'id3', name: 'Device 3', deviceClass: AppleDeviceClass.Mac },
] as AppleDevice[]);
// @ts-ignore
jest.mocked(getApplePlatformFromTarget).mockResolvedValue(ApplePlatform.IOS);
Object.defineProperty(ctx, 'appStore', { value: jest.mock('../../appstore/AppStoreApi') });
ctx.appStore.createOrReuseAdhocProvisioningProfileAsync = jest.fn().mockResolvedValue({
provisioningProfileId: 'provisioningProfileId',
} as ProvisioningProfile);
ctx.ios.createOrGetExistingAppleAppIdentifierAsync = jest
.fn()
.mockResolvedValue({} as AppleAppIdentifierFragment);
jest.mocked(assignBuildCredentialsAsync).mockResolvedValue({} as IosAppBuildCredentialsFragment);
const distCert = {} as AppleDistributionCertificateFragment;
return { ctx, distCert };
}
@@ -733,6 +733,13 @@ export const CapabilityMapping: CapabilityClassifier[] = [
validateOptions: validateBooleanOptions,
getOptions: getBooleanOptions,
},
{
entitlement: 'com.apple.developer.proximity-reader.payment.acceptance',
name: 'Tap to Pay on iPhone',
capability: CapabilityType.TAP_TO_PAY_ON_IPHONE,
validateOptions: validateBooleanOptions,
getOptions: getBooleanOptions,
},
{
entitlement: 'com.apple.developer.matter.allow-setup-payload',
name: 'Matter Allow Setup Payload',
@@ -4,12 +4,14 @@ import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/creat
import Log from '../../log';
import { pressAnyKeyToContinueAsync } from '../../prompts';
import { Actor } from '../../user/User';
import { Client } from '../../vcs/vcs';
import { CredentialsContext, CredentialsContextProjectInfo } from '../context';
export interface Action<T = void> {
actor: Actor;
graphqlClient: ExpoGraphqlClient;
analytics: Analytics;
vcsClient: Client;
projectInfo: CredentialsContextProjectInfo | null;
getDynamicPrivateProjectConfigAsync: DynamicConfigContextFn;
runAsync(ctx: CredentialsContext): Promise<T>;
@@ -27,6 +27,7 @@ import {
displayEmptyAndroidCredentials,
} from '../android/utils/printCredentials';
import { CredentialsContext, CredentialsContextProjectInfo } from '../context';
import { AndroidPackageNotDefinedError } from '../errors';
import { ActionInfo, AndroidActionType, Scope } from './Actions';
import {
buildCredentialsActions,
@@ -64,6 +65,7 @@ export class ManageAndroid {
analytics: this.callingAction.analytics,
env: buildProfile?.env,
nonInteractive: false,
vcsClient: this.callingAction.vcsClient,
});
let gradleContext;
@@ -131,6 +133,12 @@ export class ManageAndroid {
await this.runProjectSpecificActionAsync(ctx, chosenAction, gradleContext);
} catch (err) {
if (err instanceof AndroidPackageNotDefinedError) {
err.message += `\n${learnMore(
'https://docs.expo.dev/workflow/configuration/'
)} about configuration with app.json/app.config.js`;
throw err; // breaks out of the loop to avoid failing again after continuation
}
Log.error(err);
if (process.env.DEBUG) {
throw err; // breaks out of the loop so we can get stack trace
@@ -146,7 +154,7 @@ export class ManageAndroid {
buildProfile: BuildProfile<Platform.ANDROID>
): Promise<GradleBuildContext | undefined> {
assert(ctx.hasProjectContext, 'createProjectContextAsync: must have project context.');
return await resolveGradleBuildContextAsync(ctx.projectDir, buildProfile);
return await resolveGradleBuildContextAsync(ctx.projectDir, buildProfile, ctx.vcsClient);
}
private async runProjectSpecificActionAsync(
@@ -78,6 +78,7 @@ export class ManageIos {
analytics: this.callingAction.analytics,
env: buildProfile?.env,
nonInteractive: false,
vcsClient: this.callingAction.vcsClient,
});
const buildCredentialsActions = getBuildCredentialsActions(ctx);
const pushKeyActions = getPushKeyActions(ctx);
@@ -194,6 +195,7 @@ export class ManageIos {
projectDir: ctx.projectDir,
nonInteractive: ctx.nonInteractive,
exp: ctx.exp,
vcsClient: ctx.vcsClient,
},
buildProfile
);
@@ -202,6 +204,7 @@ export class ManageIos {
projectDir: ctx.projectDir,
xcodeBuildContext,
env: buildProfile.env,
vcsClient: ctx.vcsClient,
});
return {
app,
@@ -3,6 +3,7 @@ import { DynamicConfigContextFn } from '../../commandUtils/context/DynamicProjec
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { selectPlatformAsync } from '../../platform';
import { Actor } from '../../user/User';
import { Client } from '../../vcs/vcs';
import { CredentialsContextProjectInfo } from '../context';
import { ManageAndroid } from './ManageAndroid';
import { ManageIos } from './ManageIos';
@@ -11,6 +12,7 @@ export class SelectPlatform {
constructor(
public readonly actor: Actor,
public readonly graphqlClient: ExpoGraphqlClient,
public readonly vcsClient: Client,
public readonly analytics: Analytics,
public readonly projectInfo: CredentialsContextProjectInfo | null,
public readonly getDynamicPrivateProjectConfigAsync: DynamicConfigContextFn,
@@ -0,0 +1,71 @@
import { Platform } from '@expo/eas-build-job';
import { BuildProfile, EasJsonUtils } from '@expo/eas-json';
import { Analytics } from '../../../analytics/AnalyticsManager';
import { ExpoGraphqlClient } from '../../../commandUtils/context/contextUtils/createGraphqlClient';
import { learnMore } from '../../../log';
import { getProjectConfigDescription } from '../../../project/projectUtils';
import { pressAnyKeyToContinueAsync } from '../../../prompts';
import { Actor } from '../../../user/User';
import { Client } from '../../../vcs/vcs';
import { getAppLookupParamsFromContextAsync } from '../../android/actions/BuildCredentialsUtils';
import { CredentialsContextProjectInfo } from '../../context';
import { AndroidPackageNotDefinedError } from '../../errors';
import { Action } from '../HelperActions';
import { ManageAndroid } from '../ManageAndroid';
jest.mock('../../android/actions/BuildCredentialsUtils');
jest.mock('../../../prompts', () => {
return {
...jest.requireActual('../../../prompts'),
pressAnyKeyToContinueAsync: jest.fn(),
};
});
jest.mock('../../../project/projectUtils');
describe('runAsync', () => {
describe('"android.package" missing in app.json', () => {
const manageAndroid = new ManageAndroid(
{
projectInfo: {} as CredentialsContextProjectInfo,
actor: {} as Actor,
graphqlClient: {} as ExpoGraphqlClient,
analytics: {} as Analytics,
vcsClient: {} as Client,
getDynamicPrivateProjectConfigAsync: jest
.fn()
.mockResolvedValue({ exp: {}, projectId: '' }),
runAsync: jest.fn(),
} as Action,
''
);
it('does not repeat the error indefinitely and prints useful error', async () => {
jest.spyOn(EasJsonUtils, 'getBuildProfileNamesAsync').mockResolvedValue(['testProfile']);
jest
.spyOn(EasJsonUtils, 'getBuildProfileAsync')
.mockResolvedValue({} as BuildProfile<Platform.ANDROID>);
jest.mocked(getProjectConfigDescription).mockReturnValue('app.json');
jest.mocked(getAppLookupParamsFromContextAsync).mockImplementation(() => {
throw new AndroidPackageNotDefinedError(
'Specify "android.package" in app.json and run this command again.'
);
});
const pressAnyKeyToContinueAsyncMock = jest.mocked(pressAnyKeyToContinueAsync);
Array.from(Array(100)).map((_, i) => {
// continue 101 times if error is rethrown indefinitely
pressAnyKeyToContinueAsyncMock.mockResolvedValueOnce();
});
pressAnyKeyToContinueAsyncMock.mockImplementationOnce(async () => {
// fail after 102nd time
fail('test should not reach this place - if it does, the error repeats indefinitely');
});
const reThrownError = new AndroidPackageNotDefinedError(
'Specify "android.package" in app.json and run this command again.\n' +
`${learnMore(
'https://docs.expo.dev/workflow/configuration/'
)} about configuration with app.json/app.config.js`
);
await expect(manageAndroid.runAsync()).rejects.toThrow(reThrownError);
});
});
});
+329 -63
View File
@@ -479,17 +479,11 @@ export type AccountSsoConfiguration = {
};
export type AccountSsoConfigurationData = {
authEndpoint?: InputMaybe<Scalars['String']>;
authProtocol: AuthProtocolType;
authProviderIdentifier: Scalars['String'];
clientIdentifier: Scalars['String'];
clientSecret: Scalars['String'];
endSessionEndpoint?: InputMaybe<Scalars['String']>;
issuer: Scalars['String'];
jwksEndpoint?: InputMaybe<Scalars['String']>;
revokeEndpoint?: InputMaybe<Scalars['String']>;
tokenEndpoint?: InputMaybe<Scalars['String']>;
userInfoEndpoint?: InputMaybe<Scalars['String']>;
};
export type AccountSsoConfigurationMutation = {
@@ -602,6 +596,8 @@ export type Actor = {
* For example, when displaying a sentence indicating that actor X created a build or published an update.
*/
displayName: Scalars['String'];
/** Experiments associated with this actor */
experiments: Array<ActorExperiment>;
/**
* Server feature gate values for this actor, optionally filtering by desired gates.
* Only resolves for the viewer.
@@ -618,9 +614,33 @@ export type ActorFeatureGatesArgs = {
filter?: InputMaybe<Array<Scalars['String']>>;
};
export type ActorExperiment = {
__typename?: 'ActorExperiment';
createdAt: Scalars['DateTime'];
enabled: Scalars['Boolean'];
experiment: Experiment;
id: Scalars['ID'];
updatedAt: Scalars['DateTime'];
};
export type ActorExperimentMutation = {
__typename?: 'ActorExperimentMutation';
/** Create or update the value of a User Experiment */
createOrUpdateActorExperiment: ActorExperiment;
};
export type ActorExperimentMutationCreateOrUpdateActorExperimentArgs = {
enabled: Scalars['Boolean'];
experiment: Experiment;
};
export type ActorQuery = {
__typename?: 'ActorQuery';
/** Query an Actor by ID */
/**
* Query an Actor by ID
* @deprecated Public actor queries are no longer supported
*/
byId: Actor;
};
@@ -789,11 +809,13 @@ export enum AndroidBuildType {
}
export type AndroidBuilderEnvironmentInput = {
bun?: InputMaybe<Scalars['String']>;
env?: InputMaybe<Scalars['JSONObject']>;
expoCli?: InputMaybe<Scalars['String']>;
image?: InputMaybe<Scalars['String']>;
ndk?: InputMaybe<Scalars['String']>;
node?: InputMaybe<Scalars['String']>;
pnpm?: InputMaybe<Scalars['String']>;
yarn?: InputMaybe<Scalars['String']>;
};
@@ -927,7 +949,6 @@ export type AndroidKeystoreInput = {
keyAlias: Scalars['String'];
keyPassword?: InputMaybe<Scalars['String']>;
keystorePassword: Scalars['String'];
type: AndroidKeystoreType;
};
export type AndroidKeystoreMutation = {
@@ -1023,6 +1044,7 @@ export type App = Project & {
insights: AppInsights;
/** iOS app credentials for the project */
iosAppCredentials: Array<IosAppCredentials>;
isDeleting: Scalars['Boolean'];
/** Whether the latest classic update publish is using a deprecated SDK version */
isDeprecated: Scalars['Boolean'];
/** @deprecated 'likes' have been deprecated. */
@@ -1057,6 +1079,8 @@ export type App = Project & {
releaseChannels: Array<Scalars['String']>;
/** @deprecated Legacy access tokens are deprecated */
requiresAccessTokenForPushSecurity: Scalars['Boolean'];
/** Runtimes associated with this app */
runtimes: RuntimesConnection;
scopeKey: Scalars['String'];
/** SDK version of the latest classic update publish, 0.0.0 otherwise */
sdkVersion: Scalars['String'];
@@ -1113,6 +1137,7 @@ export type AppAndroidAppCredentialsArgs = {
export type AppBranchesPaginatedArgs = {
after?: InputMaybe<Scalars['String']>;
before?: InputMaybe<Scalars['String']>;
filter?: InputMaybe<BranchFilterInput>;
first?: InputMaybe<Scalars['Int']>;
last?: InputMaybe<Scalars['Int']>;
};
@@ -1174,6 +1199,7 @@ export type AppDeploymentArgs = {
export type AppDeploymentsArgs = {
after?: InputMaybe<Scalars['String']>;
before?: InputMaybe<Scalars['String']>;
filter?: InputMaybe<DeploymentFilterInput>;
first?: InputMaybe<Scalars['Int']>;
last?: InputMaybe<Scalars['Int']>;
};
@@ -1212,6 +1238,15 @@ export type AppLikedByArgs = {
};
/** Represents an Exponent App (or Experience in legacy terms) */
export type AppRuntimesArgs = {
after?: InputMaybe<Scalars['String']>;
before?: InputMaybe<Scalars['String']>;
first?: InputMaybe<Scalars['Int']>;
last?: InputMaybe<Scalars['Int']>;
};
/** Represents an Exponent App (or Experience in legacy terms) */
export type AppSubmissionsArgs = {
filter: SubmissionFilter;
@@ -1366,19 +1401,16 @@ export type AppInsights = {
export type AppInsightsTotalUniqueUsersArgs = {
timespan: InsightsTimespan;
useDeprecatedBackend?: InputMaybe<Scalars['Boolean']>;
};
export type AppInsightsUniqueUsersByAppVersionOverTimeArgs = {
timespan: InsightsTimespan;
useDeprecatedBackend?: InputMaybe<Scalars['Boolean']>;
};
export type AppInsightsUniqueUsersByPlatformOverTimeArgs = {
timespan: InsightsTimespan;
useDeprecatedBackend?: InputMaybe<Scalars['Boolean']>;
};
export type AppMutation = {
@@ -1646,6 +1678,7 @@ export type AppleDevice = {
__typename?: 'AppleDevice';
account: Account;
appleTeam: AppleTeam;
createdAt?: Maybe<Scalars['DateTime']>;
deviceClass?: Maybe<AppleDeviceClass>;
enabled?: Maybe<Scalars['Boolean']>;
id: Scalars['ID'];
@@ -2035,6 +2068,10 @@ export type BillingPeriod = {
start: Scalars['DateTime'];
};
export type BranchFilterInput = {
searchTerm?: InputMaybe<Scalars['String']>;
};
/** Represents an EAS Build */
export type Build = ActivityTimelineProjectActivity & BuildOrBuildJob & {
__typename?: 'Build';
@@ -2053,6 +2090,7 @@ export type Build = ActivityTimelineProjectActivity & BuildOrBuildJob & {
completedAt?: Maybe<Scalars['DateTime']>;
createdAt: Scalars['DateTime'];
customWorkflowName?: Maybe<Scalars['String']>;
developmentClient?: Maybe<Scalars['Boolean']>;
distribution?: Maybe<DistributionType>;
enqueuedAt?: Maybe<Scalars['DateTime']>;
error?: Maybe<BuildError>;
@@ -2087,6 +2125,7 @@ export type Build = ActivityTimelineProjectActivity & BuildOrBuildJob & {
queuePosition?: Maybe<Scalars['Int']>;
reactNativeVersion?: Maybe<Scalars['String']>;
releaseChannel?: Maybe<Scalars['String']>;
requiredPackageManager?: Maybe<Scalars['String']>;
/**
* The builder resource class requested by the developer
* @deprecated Use resourceClassDisplayName instead
@@ -2144,6 +2183,7 @@ export enum BuildCredentialsSource {
export type BuildError = {
__typename?: 'BuildError';
buildPhase?: Maybe<BuildPhase>;
docsUrl?: Maybe<Scalars['String']>;
errorCode: Scalars['String'];
message: Scalars['String'];
@@ -2269,6 +2309,7 @@ export type BuildMetadataInput = {
cliVersion?: InputMaybe<Scalars['String']>;
credentialsSource?: InputMaybe<BuildCredentialsSource>;
customWorkflowName?: InputMaybe<Scalars['String']>;
developmentClient?: InputMaybe<Scalars['Boolean']>;
distribution?: InputMaybe<DistributionType>;
gitCommitHash?: InputMaybe<Scalars['String']>;
gitCommitMessage?: InputMaybe<Scalars['String']>;
@@ -2277,6 +2318,7 @@ export type BuildMetadataInput = {
message?: InputMaybe<Scalars['String']>;
reactNativeVersion?: InputMaybe<Scalars['String']>;
releaseChannel?: InputMaybe<Scalars['String']>;
requiredPackageManager?: InputMaybe<Scalars['String']>;
runFromCI?: InputMaybe<Scalars['Boolean']>;
runWithNoWaitFlag?: InputMaybe<Scalars['Boolean']>;
runtimeVersion?: InputMaybe<Scalars['String']>;
@@ -2397,6 +2439,50 @@ export type BuildParamsInput = {
sdkVersion?: InputMaybe<Scalars['String']>;
};
export enum BuildPhase {
BuilderInfo = 'BUILDER_INFO',
CleanUpCredentials = 'CLEAN_UP_CREDENTIALS',
CompleteBuild = 'COMPLETE_BUILD',
ConfigureExpoUpdates = 'CONFIGURE_EXPO_UPDATES',
ConfigureXcodeProject = 'CONFIGURE_XCODE_PROJECT',
Custom = 'CUSTOM',
DownloadApplicationArchive = 'DOWNLOAD_APPLICATION_ARCHIVE',
EasBuildInternal = 'EAS_BUILD_INTERNAL',
FailBuild = 'FAIL_BUILD',
FixGradlew = 'FIX_GRADLEW',
InstallCustomTools = 'INSTALL_CUSTOM_TOOLS',
InstallDependencies = 'INSTALL_DEPENDENCIES',
InstallPods = 'INSTALL_PODS',
OnBuildCancelHook = 'ON_BUILD_CANCEL_HOOK',
OnBuildCompleteHook = 'ON_BUILD_COMPLETE_HOOK',
OnBuildErrorHook = 'ON_BUILD_ERROR_HOOK',
OnBuildSuccessHook = 'ON_BUILD_SUCCESS_HOOK',
ParseCustomWorkflowConfig = 'PARSE_CUSTOM_WORKFLOW_CONFIG',
PostInstallHook = 'POST_INSTALL_HOOK',
Prebuild = 'PREBUILD',
PrepareArtifacts = 'PREPARE_ARTIFACTS',
PrepareCredentials = 'PREPARE_CREDENTIALS',
PrepareProject = 'PREPARE_PROJECT',
PreInstallHook = 'PRE_INSTALL_HOOK',
PreUploadArtifactsHook = 'PRE_UPLOAD_ARTIFACTS_HOOK',
Queue = 'QUEUE',
ReadAppConfig = 'READ_APP_CONFIG',
ReadPackageJson = 'READ_PACKAGE_JSON',
RestoreCache = 'RESTORE_CACHE',
RunExpoDoctor = 'RUN_EXPO_DOCTOR',
RunFastlane = 'RUN_FASTLANE',
RunGradlew = 'RUN_GRADLEW',
SaveCache = 'SAVE_CACHE',
SetUpBuildEnvironment = 'SET_UP_BUILD_ENVIRONMENT',
SpinUpBuilder = 'SPIN_UP_BUILDER',
StartBuild = 'START_BUILD',
Unknown = 'UNKNOWN',
UploadApplicationArchive = 'UPLOAD_APPLICATION_ARCHIVE',
/** @deprecated No longer supported */
UploadArtifacts = 'UPLOAD_ARTIFACTS',
UploadBuildArtifacts = 'UPLOAD_BUILD_ARTIFACTS'
}
export type BuildPlanCreditThresholdExceededMetadata = {
__typename?: 'BuildPlanCreditThresholdExceededMetadata';
account: Account;
@@ -2771,8 +2857,10 @@ export type Deployment = {
builds: DeploymentBuildsConnection;
channel: UpdateChannel;
id: Scalars['ID'];
/** @deprecated Not required for the new Deployment UI */
latestUpdate?: Maybe<Update>;
/** Deployment query field */
insights: DeploymentInsights;
/** Ordered the same way as 'updateBranches' in UpdateChannel */
latestUpdatesPerBranch: Array<LatestUpdateOnBranch>;
runtime: Runtime;
};
@@ -2785,6 +2873,13 @@ export type DeploymentBuildsArgs = {
last?: InputMaybe<Scalars['Int']>;
};
/** Represents a Deployment - a set of Builds with the same Runtime Version and Channel */
export type DeploymentLatestUpdatesPerBranchArgs = {
limit: Scalars['Int'];
offset: Scalars['Int'];
};
export type DeploymentBuildEdge = {
__typename?: 'DeploymentBuildEdge';
cursor: Scalars['String'];
@@ -2804,6 +2899,40 @@ export type DeploymentEdge = {
node: Deployment;
};
export type DeploymentFilterInput = {
channel?: InputMaybe<Scalars['String']>;
runtimeVersion?: InputMaybe<Scalars['String']>;
};
export type DeploymentInsights = {
__typename?: 'DeploymentInsights';
embeddedUpdateTotalUniqueUsers: Scalars['Int'];
embeddedUpdateUniqueUsersOverTime: UniqueUsersOverTimeData;
id: Scalars['ID'];
mostPopularUpdates: Array<Update>;
uniqueUsersOverTime: UniqueUsersOverTimeData;
};
export type DeploymentInsightsEmbeddedUpdateTotalUniqueUsersArgs = {
timespan: InsightsTimespan;
};
export type DeploymentInsightsEmbeddedUpdateUniqueUsersOverTimeArgs = {
timespan: InsightsTimespan;
};
export type DeploymentInsightsMostPopularUpdatesArgs = {
timespan: InsightsTimespan;
};
export type DeploymentInsightsUniqueUsersOverTimeArgs = {
timespan: InsightsTimespan;
};
/** Represents the connection over the deployments edge of an App */
export type DeploymentsConnection = {
__typename?: 'DeploymentsConnection';
@@ -2972,6 +3101,10 @@ export type EstimatedUsage = {
value: Scalars['Float'];
};
export enum Experiment {
Orbit = 'ORBIT'
}
export type ExperimentationQuery = {
__typename?: 'ExperimentationQuery';
/** Get device experimentation config */
@@ -3137,6 +3270,10 @@ export type GitHubBuildTrigger = {
id: Scalars['ID'];
isActive: Scalars['Boolean'];
lastRunAt?: Maybe<Scalars['DateTime']>;
lastRunBuild?: Maybe<Build>;
lastRunErrorCode?: Maybe<Scalars['String']>;
lastRunErrorMessage?: Maybe<Scalars['String']>;
lastRunStatus?: Maybe<GitHubBuildTriggerRunStatus>;
platform: AppPlatform;
sourcePattern: Scalars['String'];
targetPattern?: Maybe<Scalars['String']>;
@@ -3170,6 +3307,11 @@ export type GitHubBuildTriggerMutationUpdateGitHubBuildTriggerArgs = {
githubBuildTriggerId: Scalars['ID'];
};
export enum GitHubBuildTriggerRunStatus {
Errored = 'ERRORED',
Success = 'SUCCESS'
}
export enum GitHubBuildTriggerType {
PullRequestUpdated = 'PULL_REQUEST_UPDATED',
PushToBranch = 'PUSH_TO_BRANCH',
@@ -3535,6 +3677,7 @@ export enum IosBuildType {
}
export type IosBuilderEnvironmentInput = {
bun?: InputMaybe<Scalars['String']>;
bundler?: InputMaybe<Scalars['String']>;
cocoapods?: InputMaybe<Scalars['String']>;
env?: InputMaybe<Scalars['JSONObject']>;
@@ -3542,6 +3685,7 @@ export type IosBuilderEnvironmentInput = {
fastlane?: InputMaybe<Scalars['String']>;
image?: InputMaybe<Scalars['String']>;
node?: InputMaybe<Scalars['String']>;
pnpm?: InputMaybe<Scalars['String']>;
yarn?: InputMaybe<Scalars['String']>;
};
@@ -3668,6 +3812,12 @@ export type KeystoreGenerationUrlMutation = {
createKeystoreGenerationUrl: KeystoreGenerationUrl;
};
export type LatestUpdateOnBranch = {
__typename?: 'LatestUpdateOnBranch';
branchId: Scalars['String'];
update?: Maybe<Update>;
};
export type LeaveAccountResult = {
__typename?: 'LeaveAccountResult';
success: Scalars['Boolean'];
@@ -3845,6 +3995,7 @@ export type MeteredBillingStatus = {
export type Notification = {
__typename?: 'Notification';
accountName: Scalars['String'];
createdAt: Scalars['DateTime'];
event: NotificationEvent;
id: Scalars['ID'];
@@ -3852,6 +4003,7 @@ export type Notification = {
metadata?: Maybe<NotificationMetadata>;
type: NotificationType;
updatedAt: Scalars['DateTime'];
websiteMessage: Scalars['String'];
};
export enum NotificationEvent {
@@ -4084,6 +4236,8 @@ export type Robot = Actor & {
accounts: Array<Account>;
created: Scalars['DateTime'];
displayName: Scalars['String'];
/** Experiments associated with this actor */
experiments: Array<ActorExperiment>;
/**
* Server feature gate values for this actor, optionally filtering by desired gates.
* Only resolves for the viewer.
@@ -4155,6 +4309,8 @@ export type RootMutation = {
account: AccountMutation;
/** Mutations that create, update, and delete an AccountSSOConfiguration */
accountSSOConfiguration: AccountSsoConfigurationMutation;
/** Mutations for Actor experiments */
actorExperiment: ActorExperimentMutation;
/** Mutations that modify the build credentials for an Android app */
androidAppBuildCredentials: AndroidAppBuildCredentialsMutation;
/** Mutations that modify the credentials for an Android app */
@@ -4226,10 +4382,14 @@ export type RootMutation = {
updateBranch: UpdateBranchMutation;
updateChannel: UpdateChannelMutation;
uploadSession: UploadSession;
/** Mutations that create, update, and delete pinned apps */
userAppPins: UserAppPinMutation;
/** Mutations that create, delete, and accept UserInvitations */
userInvitation: UserInvitationMutation;
/** Mutations that create, delete, update Webhooks */
webhook: WebhookMutation;
/** Mutations that modify a websiteNotification */
websiteNotifications: WebsiteNotificationMutation;
};
@@ -4263,7 +4423,10 @@ export type RootQuery = {
account: AccountQuery;
/** Top-level query object for querying AccountSSOConfigurationPublicData */
accountSSOConfigurationPublicData: AccountSsoConfigurationPublicDataQuery;
/** Top-level query object for querying Actors. */
/**
* Top-level query object for querying Actors.
* @deprecated Public actor queries are no longer supported
*/
actor: ActorQuery;
/**
* Public apps in the app directory
@@ -4320,7 +4483,10 @@ export type RootQuery = {
* @deprecated Public user queries are no longer supported
*/
user: UserQuery;
/** Top-level query object for querying UserActors. */
/**
* Top-level query object for querying UserActors.
* @deprecated Public user queries are no longer supported
*/
userActor: UserActorQuery;
/** Top-level query object for querying UserActorPublicData publicly. */
userActorPublicData: UserActorPublicDataQuery;
@@ -4386,6 +4552,7 @@ export type RuntimeFilterInput = {
branchId?: InputMaybe<Scalars['String']>;
};
/** Represents the connection over the runtime edge of an App */
export type RuntimesConnection = {
__typename?: 'RuntimesConnection';
edges: Array<RuntimeEdge>;
@@ -4410,6 +4577,8 @@ export type SsoUser = Actor & UserActor & {
/** Discord account linked to a user */
discordUser?: Maybe<DiscordUser>;
displayName: Scalars['String'];
/** Experiments associated with this actor */
experiments: Array<ActorExperiment>;
/**
* Server feature gate values for this actor, optionally filtering by desired gates.
* Only resolves for the viewer.
@@ -4429,6 +4598,7 @@ export type SsoUser = Actor & UserActor & {
/** @deprecated No longer supported */
location?: Maybe<Scalars['String']>;
notificationSubscriptions: Array<NotificationSubscription>;
pinnedApps: Array<App>;
/** Associated accounts */
primaryAccount: Account;
profilePhoto: Scalars['String'];
@@ -4437,8 +4607,7 @@ export type SsoUser = Actor & UserActor & {
/** @deprecated No longer supported */
twitterUsername?: Maybe<Scalars['String']>;
username: Scalars['String'];
/** Web notifications linked to a user */
websiteNotifications: Array<Notification>;
websiteNotificationsPaginated: WebsiteNotificationsConnection;
};
@@ -4476,6 +4645,15 @@ export type SsoUserSnacksArgs = {
offset: Scalars['Int'];
};
/** Represents a human SSO (not robot) actor. */
export type SsoUserWebsiteNotificationsPaginatedArgs = {
after?: InputMaybe<Scalars['String']>;
before?: InputMaybe<Scalars['String']>;
first?: InputMaybe<Scalars['Int']>;
last?: InputMaybe<Scalars['Int']>;
};
export type SsoUserDataInput = {
firstName?: InputMaybe<Scalars['String']>;
lastName?: InputMaybe<Scalars['String']>;
@@ -4670,7 +4848,9 @@ export type StatuspageService = {
export enum StatuspageServiceName {
EasBuild = 'EAS_BUILD',
EasSubmit = 'EAS_SUBMIT',
EasUpdate = 'EAS_UPDATE'
EasUpdate = 'EAS_UPDATE',
GithubApiRequests = 'GITHUB_API_REQUESTS',
GithubWebhooks = 'GITHUB_WEBHOOKS'
}
export type StatuspageServiceQuery = {
@@ -4904,6 +5084,8 @@ export type Update = ActivityTimelineProjectActivity & {
gitCommitHash?: Maybe<Scalars['String']>;
group: Scalars['String'];
id: Scalars['ID'];
/** Update query field */
insights: UpdateInsights;
isGitWorkingTreeDirty: Scalars['Boolean'];
isRollBackToEmbedded: Scalars['Boolean'];
manifestFragment: Scalars['String'];
@@ -5064,6 +5246,17 @@ export type UpdateInfoGroup = {
web?: InputMaybe<PartialManifest>;
};
export type UpdateInsights = {
__typename?: 'UpdateInsights';
id: Scalars['ID'];
totalUniqueUsers: Scalars['Int'];
};
export type UpdateInsightsTotalUniqueUsersArgs = {
timespan: InsightsTimespan;
};
export type UpdateMutation = {
__typename?: 'UpdateMutation';
/** Delete an EAS update group */
@@ -5163,6 +5356,8 @@ export type User = Actor & UserActor & {
displayName: Scalars['String'];
email: Scalars['String'];
emailVerified: Scalars['Boolean'];
/** Experiments associated with this actor */
experiments: Array<ActorExperiment>;
/**
* Server feature gate values for this actor, optionally filtering by desired gates.
* Only resolves for the viewer.
@@ -5189,6 +5384,7 @@ export type User = Actor & UserActor & {
notificationSubscriptions: Array<NotificationSubscription>;
/** Pending UserInvitations for this user. Only resolves for the viewer. */
pendingUserInvitations: Array<UserInvitation>;
pinnedApps: Array<App>;
/** Associated accounts */
primaryAccount: Account;
profilePhoto: Scalars['String'];
@@ -5199,7 +5395,7 @@ export type User = Actor & UserActor & {
/** @deprecated No longer supported */
twitterUsername?: Maybe<Scalars['String']>;
username: Scalars['String'];
websiteNotifications: Array<Notification>;
websiteNotificationsPaginated: WebsiteNotificationsConnection;
};
@@ -5237,6 +5433,15 @@ export type UserSnacksArgs = {
offset: Scalars['Int'];
};
/** Represents a human (not robot) actor. */
export type UserWebsiteNotificationsPaginatedArgs = {
after?: InputMaybe<Scalars['String']>;
before?: InputMaybe<Scalars['String']>;
first?: InputMaybe<Scalars['Int']>;
last?: InputMaybe<Scalars['Int']>;
};
/** A human user (type User or SSOUser) that can login to the Expo website, use Expo services, and be a member of accounts. */
export type UserActor = {
/** Access Tokens belonging to this user actor */
@@ -5261,6 +5466,8 @@ export type UserActor = {
* For example, when displaying a sentence indicating that actor X created a build or published an update.
*/
displayName: Scalars['String'];
/** Experiments associated with this actor */
experiments: Array<ActorExperiment>;
/**
* Server feature gate values for this user actor, optionally filtering by desired gates.
* Only resolves for the viewer.
@@ -5280,6 +5487,7 @@ export type UserActor = {
/** @deprecated No longer supported */
location?: Maybe<Scalars['String']>;
notificationSubscriptions: Array<NotificationSubscription>;
pinnedApps: Array<App>;
/** Associated accounts */
primaryAccount: Account;
profilePhoto: Scalars['String'];
@@ -5288,8 +5496,7 @@ export type UserActor = {
/** @deprecated No longer supported */
twitterUsername?: Maybe<Scalars['String']>;
username: Scalars['String'];
/** Web notifications linked to a user */
websiteNotifications: Array<Notification>;
websiteNotificationsPaginated: WebsiteNotificationsConnection;
};
@@ -5327,6 +5534,15 @@ export type UserActorSnacksArgs = {
offset: Scalars['Int'];
};
/** A human user (type User or SSOUser) that can login to the Expo website, use Expo services, and be a member of accounts. */
export type UserActorWebsiteNotificationsPaginatedArgs = {
after?: InputMaybe<Scalars['String']>;
before?: InputMaybe<Scalars['String']>;
first?: InputMaybe<Scalars['Int']>;
last?: InputMaybe<Scalars['Int']>;
};
/** A human user (type User or SSOUser) that can login to the Expo website, use Expo services, and be a member of accounts. */
export type UserActorPublicData = {
__typename?: 'UserActorPublicData';
@@ -5369,9 +5585,15 @@ export type UserActorPublicDataQueryByUsernameArgs = {
export type UserActorQuery = {
__typename?: 'UserActorQuery';
/** Query a UserActor by ID */
/**
* Query a UserActor by ID
* @deprecated Public user actor queries are no longer supported
*/
byId: UserActor;
/** Query a UserActor by username */
/**
* Query a UserActor by username
* @deprecated Public user actor queries are no longer supported
*/
byUsername: UserActor;
};
@@ -5385,6 +5607,22 @@ export type UserActorQueryByUsernameArgs = {
username: Scalars['String'];
};
export type UserAppPinMutation = {
__typename?: 'UserAppPinMutation';
pinApp: Scalars['ID'];
unpinApp?: Maybe<Scalars['ID']>;
};
export type UserAppPinMutationPinAppArgs = {
appId: Scalars['ID'];
};
export type UserAppPinMutationUnpinAppArgs = {
appId: Scalars['ID'];
};
export type UserDataInput = {
email?: InputMaybe<Scalars['String']>;
firstName?: InputMaybe<Scalars['String']>;
@@ -5544,6 +5782,11 @@ export type UserSecondFactorDevice = {
user: User;
};
export type WebNotificationUpdateReadStateInput = {
id: Scalars['ID'];
isRead: Scalars['Boolean'];
};
export type Webhook = {
__typename?: 'Webhook';
appId: Scalars['ID'];
@@ -5606,6 +5849,29 @@ export enum WebhookType {
Submit = 'SUBMIT'
}
export type WebsiteNotificationEdge = {
__typename?: 'WebsiteNotificationEdge';
cursor: Scalars['String'];
node: Notification;
};
export type WebsiteNotificationMutation = {
__typename?: 'WebsiteNotificationMutation';
updateAllWebsiteNotificationReadStateAsRead: Scalars['Boolean'];
updateNotificationReadState: Notification;
};
export type WebsiteNotificationMutationUpdateNotificationReadStateArgs = {
input: WebNotificationUpdateReadStateInput;
};
export type WebsiteNotificationsConnection = {
__typename?: 'WebsiteNotificationsConnection';
edges: Array<WebsiteNotificationEdge>;
pageInfo: PageInfo;
};
export type DeleteAndroidAppBuildCredentialsResult = {
__typename?: 'deleteAndroidAppBuildCredentialsResult';
id: Scalars['ID'];
@@ -5732,7 +5998,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, 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, 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'];
@@ -5740,7 +6006,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, 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, 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'];
@@ -5748,7 +6014,7 @@ export type SetGoogleServiceAccountKeyForSubmissionsMutationVariables = Exact<{
}>;
export type SetGoogleServiceAccountKeyForSubmissionsMutation = { __typename?: 'RootMutation', androidAppCredentials: { __typename?: 'AndroidAppCredentialsMutation', setGoogleServiceAccountKeyForSubmissions: { __typename?: 'AndroidAppCredentials', id: string, applicationIdentifier?: string | null, isLegacy: boolean, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, 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, 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;
@@ -5802,7 +6068,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, 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, 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'];
@@ -5840,7 +6106,7 @@ export type CreateAppleDeviceMutationVariables = Exact<{
}>;
export type CreateAppleDeviceMutation = { __typename?: 'RootMutation', appleDevice: { __typename?: 'AppleDeviceMutation', createAppleDevice: { __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null } } };
export type CreateAppleDeviceMutation = { __typename?: 'RootMutation', appleDevice: { __typename?: 'AppleDeviceMutation', createAppleDevice: { __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt?: any | null } } };
export type DeleteAppleDeviceMutationVariables = Exact<{
deviceId: Scalars['ID'];
@@ -5855,7 +6121,7 @@ export type UpdateAppleDeviceMutationVariables = Exact<{
}>;
export type UpdateAppleDeviceMutation = { __typename?: 'RootMutation', appleDevice: { __typename?: 'AppleDeviceMutation', updateAppleDevice: { __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null } } };
export type UpdateAppleDeviceMutation = { __typename?: 'RootMutation', appleDevice: { __typename?: 'AppleDeviceMutation', updateAppleDevice: { __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt?: any | null } } };
export type CreateAppleDeviceRegistrationRequestMutationVariables = Exact<{
appleTeamId: Scalars['ID'];
@@ -5871,7 +6137,7 @@ export type CreateAppleDistributionCertificateMutationVariables = Exact<{
}>;
export type CreateAppleDistributionCertificateMutation = { __typename?: 'RootMutation', appleDistributionCertificate: { __typename?: 'AppleDistributionCertificateMutation', createAppleDistributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null } };
export type CreateAppleDistributionCertificateMutation = { __typename?: 'RootMutation', appleDistributionCertificate: { __typename?: 'AppleDistributionCertificateMutation', createAppleDistributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null } };
export type DeleteAppleDistributionCertificateMutationVariables = Exact<{
appleDistributionCertificateId: Scalars['ID'];
@@ -5887,7 +6153,7 @@ export type CreateAppleProvisioningProfileMutationVariables = Exact<{
}>;
export type CreateAppleProvisioningProfileMutation = { __typename?: 'RootMutation', appleProvisioningProfile: { __typename?: 'AppleProvisioningProfileMutation', createAppleProvisioningProfile: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null }> } } };
export type CreateAppleProvisioningProfileMutation = { __typename?: 'RootMutation', appleProvisioningProfile: { __typename?: 'AppleProvisioningProfileMutation', createAppleProvisioningProfile: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt?: any | null }> } } };
export type UpdateAppleProvisioningProfileMutationVariables = Exact<{
appleProvisioningProfileId: Scalars['ID'];
@@ -5895,7 +6161,7 @@ export type UpdateAppleProvisioningProfileMutationVariables = Exact<{
}>;
export type UpdateAppleProvisioningProfileMutation = { __typename?: 'RootMutation', appleProvisioningProfile: { __typename?: 'AppleProvisioningProfileMutation', updateAppleProvisioningProfile: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null }> } } };
export type UpdateAppleProvisioningProfileMutation = { __typename?: 'RootMutation', appleProvisioningProfile: { __typename?: 'AppleProvisioningProfileMutation', updateAppleProvisioningProfile: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt?: any | null }> } } };
export type DeleteAppleProvisioningProfilesMutationVariables = Exact<{
appleProvisioningProfileIds: Array<Scalars['ID']> | Scalars['ID'];
@@ -5910,7 +6176,7 @@ export type CreateApplePushKeyMutationVariables = Exact<{
}>;
export type CreateApplePushKeyMutation = { __typename?: 'RootMutation', applePushKey: { __typename?: 'ApplePushKeyMutation', createApplePushKey: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } } };
export type CreateApplePushKeyMutation = { __typename?: 'RootMutation', applePushKey: { __typename?: 'ApplePushKeyMutation', createApplePushKey: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } } };
export type DeleteApplePushKeyMutationVariables = Exact<{
applePushKeyId: Scalars['ID'];
@@ -5925,7 +6191,7 @@ export type CreateAppleTeamMutationVariables = Exact<{
}>;
export type CreateAppleTeamMutation = { __typename?: 'RootMutation', appleTeam: { __typename?: 'AppleTeamMutation', createAppleTeam: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null, account: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } } } };
export type CreateAppleTeamMutation = { __typename?: 'RootMutation', appleTeam: { __typename?: 'AppleTeamMutation', createAppleTeam: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null, account: { __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 CreateIosAppBuildCredentialsMutationVariables = Exact<{
iosAppBuildCredentialsInput: IosAppBuildCredentialsInput;
@@ -5933,7 +6199,7 @@ export type CreateIosAppBuildCredentialsMutationVariables = Exact<{
}>;
export type CreateIosAppBuildCredentialsMutation = { __typename?: 'RootMutation', iosAppBuildCredentials: { __typename?: 'IosAppBuildCredentialsMutation', createIosAppBuildCredentials: { __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null }> } | null } } };
export type CreateIosAppBuildCredentialsMutation = { __typename?: 'RootMutation', iosAppBuildCredentials: { __typename?: 'IosAppBuildCredentialsMutation', createIosAppBuildCredentials: { __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt?: any | null }> } | null } } };
export type SetDistributionCertificateMutationVariables = Exact<{
iosAppBuildCredentialsId: Scalars['ID'];
@@ -5941,7 +6207,7 @@ export type SetDistributionCertificateMutationVariables = Exact<{
}>;
export type SetDistributionCertificateMutation = { __typename?: 'RootMutation', iosAppBuildCredentials: { __typename?: 'IosAppBuildCredentialsMutation', setDistributionCertificate: { __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null }> } | null } } };
export type SetDistributionCertificateMutation = { __typename?: 'RootMutation', iosAppBuildCredentials: { __typename?: 'IosAppBuildCredentialsMutation', setDistributionCertificate: { __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt?: any | null }> } | null } } };
export type SetProvisioningProfileMutationVariables = Exact<{
iosAppBuildCredentialsId: Scalars['ID'];
@@ -5949,7 +6215,7 @@ export type SetProvisioningProfileMutationVariables = Exact<{
}>;
export type SetProvisioningProfileMutation = { __typename?: 'RootMutation', iosAppBuildCredentials: { __typename?: 'IosAppBuildCredentialsMutation', setProvisioningProfile: { __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null }> } | null } } };
export type SetProvisioningProfileMutation = { __typename?: 'RootMutation', iosAppBuildCredentials: { __typename?: 'IosAppBuildCredentialsMutation', setProvisioningProfile: { __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt?: any | null }> } | null } } };
export type CreateIosAppCredentialsMutationVariables = Exact<{
iosAppCredentialsInput: IosAppCredentialsInput;
@@ -5958,7 +6224,7 @@ export type CreateIosAppCredentialsMutationVariables = Exact<{
}>;
export type CreateIosAppCredentialsMutation = { __typename?: 'RootMutation', iosAppCredentials: { __typename?: 'IosAppCredentialsMutation', createIosAppCredentials: { __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null }> } | null }>, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string }, pushKey?: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } | null, appStoreConnectApiKeyForSubmissions?: { __typename?: 'AppStoreConnectApiKey', id: string, issuerIdentifier: string, keyIdentifier: string, name?: string | null, roles?: Array<AppStoreConnectUserRole> | null, createdAt: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null } | null } } };
export type CreateIosAppCredentialsMutation = { __typename?: 'RootMutation', iosAppCredentials: { __typename?: 'IosAppCredentialsMutation', createIosAppCredentials: { __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt?: any | null }> } | null }>, 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 } }> } }, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string }, pushKey?: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } | null, appStoreConnectApiKeyForSubmissions?: { __typename?: 'AppStoreConnectApiKey', id: string, issuerIdentifier: string, keyIdentifier: string, name?: string | null, roles?: Array<AppStoreConnectUserRole> | null, createdAt: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null } | null } } };
export type SetPushKeyMutationVariables = Exact<{
iosAppCredentialsId: Scalars['ID'];
@@ -5966,7 +6232,7 @@ export type SetPushKeyMutationVariables = Exact<{
}>;
export type SetPushKeyMutation = { __typename?: 'RootMutation', iosAppCredentials: { __typename?: 'IosAppCredentialsMutation', setPushKey: { __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null }> } | null }>, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string }, pushKey?: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } | null, appStoreConnectApiKeyForSubmissions?: { __typename?: 'AppStoreConnectApiKey', id: string, issuerIdentifier: string, keyIdentifier: string, name?: string | null, roles?: Array<AppStoreConnectUserRole> | null, createdAt: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null } | null } } };
export type SetPushKeyMutation = { __typename?: 'RootMutation', iosAppCredentials: { __typename?: 'IosAppCredentialsMutation', setPushKey: { __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt?: any | null }> } | null }>, 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 } }> } }, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string }, pushKey?: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } | null, appStoreConnectApiKeyForSubmissions?: { __typename?: 'AppStoreConnectApiKey', id: string, issuerIdentifier: string, keyIdentifier: string, name?: string | null, roles?: Array<AppStoreConnectUserRole> | null, createdAt: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null } | null } } };
export type SetAppStoreConnectApiKeyForSubmissionsMutationVariables = Exact<{
iosAppCredentialsId: Scalars['ID'];
@@ -5974,7 +6240,7 @@ export type SetAppStoreConnectApiKeyForSubmissionsMutationVariables = Exact<{
}>;
export type SetAppStoreConnectApiKeyForSubmissionsMutation = { __typename?: 'RootMutation', iosAppCredentials: { __typename?: 'IosAppCredentialsMutation', setAppStoreConnectApiKeyForSubmissions: { __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null }> } | null }>, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string }, pushKey?: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } | null, appStoreConnectApiKeyForSubmissions?: { __typename?: 'AppStoreConnectApiKey', id: string, issuerIdentifier: string, keyIdentifier: string, name?: string | null, roles?: Array<AppStoreConnectUserRole> | null, createdAt: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null } | null } } };
export type SetAppStoreConnectApiKeyForSubmissionsMutation = { __typename?: 'RootMutation', iosAppCredentials: { __typename?: 'IosAppCredentialsMutation', setAppStoreConnectApiKeyForSubmissions: { __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt?: any | null }> } | null }>, 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 } }> } }, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string }, pushKey?: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } | null, appStoreConnectApiKeyForSubmissions?: { __typename?: 'AppStoreConnectApiKey', id: string, issuerIdentifier: string, keyIdentifier: string, name?: string | null, roles?: Array<AppStoreConnectUserRole> | null, createdAt: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null } | null } } };
export type AppStoreConnectApiKeyByAccountQueryVariables = Exact<{
accountName: Scalars['String'];
@@ -5997,7 +6263,7 @@ export type AppleDevicesByAppleTeamQueryVariables = Exact<{
}>;
export type AppleDevicesByAppleTeamQuery = { __typename?: 'RootQuery', appleTeam: { __typename?: 'AppleTeamQuery', byAppleTeamIdentifier?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, appleTeam: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } }> } | null } };
export type AppleDevicesByAppleTeamQuery = { __typename?: 'RootQuery', appleTeam: { __typename?: 'AppleTeamQuery', byAppleTeamIdentifier?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt?: any | null, appleTeam: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } }> } | null } };
export type AppleDevicesByTeamIdentifierQueryVariables = Exact<{
accountName: Scalars['String'];
@@ -6024,14 +6290,14 @@ export type AppleDistributionCertificateByAppQueryVariables = Exact<{
}>;
export type AppleDistributionCertificateByAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byFullName: { __typename?: 'App', id: string, iosAppCredentials: Array<{ __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null }> }> } } };
export type AppleDistributionCertificateByAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byFullName: { __typename?: 'App', id: string, iosAppCredentials: Array<{ __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null }> }> } } };
export type AppleDistributionCertificateByAccountQueryVariables = Exact<{
accountName: Scalars['String'];
}>;
export type AppleDistributionCertificateByAccountQuery = { __typename?: 'RootQuery', account: { __typename?: 'AccountQuery', byName: { __typename?: 'Account', id: string, appleDistributionCertificates: Array<{ __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> }> } } };
export type AppleDistributionCertificateByAccountQuery = { __typename?: 'RootQuery', account: { __typename?: 'AccountQuery', byName: { __typename?: 'Account', id: string, appleDistributionCertificates: Array<{ __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> }> } } };
export type AppleProvisioningProfilesByAppQueryVariables = Exact<{
projectFullName: Scalars['String'];
@@ -6040,14 +6306,14 @@ export type AppleProvisioningProfilesByAppQueryVariables = Exact<{
}>;
export type AppleProvisioningProfilesByAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byFullName: { __typename?: 'App', id: string, iosAppCredentials: Array<{ __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null }>, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } } | null }> }> } } };
export type AppleProvisioningProfilesByAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byFullName: { __typename?: 'App', id: string, iosAppCredentials: Array<{ __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt?: any | null }>, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } } | null }> }> } } };
export type ApplePushKeyByAccountQueryVariables = Exact<{
accountName: Scalars['String'];
}>;
export type ApplePushKeyByAccountQuery = { __typename?: 'RootQuery', account: { __typename?: 'AccountQuery', byName: { __typename?: 'Account', id: string, applePushKeys: Array<{ __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> }> } } };
export type ApplePushKeyByAccountQuery = { __typename?: 'RootQuery', account: { __typename?: 'AccountQuery', byName: { __typename?: 'Account', id: string, applePushKeys: Array<{ __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> }> } } };
export type AppleTeamsByAccountNameQueryVariables = Exact<{
accountName: Scalars['String'];
@@ -6073,7 +6339,7 @@ export type IosAppBuildCredentialsByAppleAppIdentiferAndDistributionQueryVariabl
}>;
export type IosAppBuildCredentialsByAppleAppIdentiferAndDistributionQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byFullName: { __typename?: 'App', id: string, iosAppCredentials: Array<{ __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null }> } | null }> }> } } };
export type IosAppBuildCredentialsByAppleAppIdentiferAndDistributionQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byFullName: { __typename?: 'App', id: string, iosAppCredentials: Array<{ __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt?: any | null }> } | null }> }> } } };
export type IosAppCredentialsWithBuildCredentialsByAppIdentifierIdQueryVariables = Exact<{
projectFullName: Scalars['String'];
@@ -6082,7 +6348,7 @@ export type IosAppCredentialsWithBuildCredentialsByAppIdentifierIdQueryVariables
}>;
export type IosAppCredentialsWithBuildCredentialsByAppIdentifierIdQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byFullName: { __typename?: 'App', id: string, iosAppCredentials: Array<{ __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null }> } | null }>, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string }, pushKey?: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } | null, appStoreConnectApiKeyForSubmissions?: { __typename?: 'AppStoreConnectApiKey', id: string, issuerIdentifier: string, keyIdentifier: string, name?: string | null, roles?: Array<AppStoreConnectUserRole> | null, createdAt: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null } | null }> } } };
export type IosAppCredentialsWithBuildCredentialsByAppIdentifierIdQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byFullName: { __typename?: 'App', id: string, iosAppCredentials: Array<{ __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt?: any | null }> } | null }>, 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 } }> } }, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string }, pushKey?: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } | null, appStoreConnectApiKeyForSubmissions?: { __typename?: 'AppStoreConnectApiKey', id: string, issuerIdentifier: string, keyIdentifier: string, name?: string | null, roles?: Array<AppStoreConnectUserRole> | null, createdAt: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null } | null }> } } };
export type CommonIosAppCredentialsWithBuildCredentialsByAppIdentifierIdQueryVariables = Exact<{
projectFullName: Scalars['String'];
@@ -6090,7 +6356,7 @@ export type CommonIosAppCredentialsWithBuildCredentialsByAppIdentifierIdQueryVar
}>;
export type CommonIosAppCredentialsWithBuildCredentialsByAppIdentifierIdQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byFullName: { __typename?: 'App', id: string, iosAppCredentials: Array<{ __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null }> } | null }>, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string }, pushKey?: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } | null, appStoreConnectApiKeyForSubmissions?: { __typename?: 'AppStoreConnectApiKey', id: string, issuerIdentifier: string, keyIdentifier: string, name?: string | null, roles?: Array<AppStoreConnectUserRole> | null, createdAt: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null } | null }> } } };
export type CommonIosAppCredentialsWithBuildCredentialsByAppIdentifierIdQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byFullName: { __typename?: 'App', id: string, iosAppCredentials: Array<{ __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt?: any | null }> } | null }>, 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 } }> } }, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string }, pushKey?: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } | null, appStoreConnectApiKeyForSubmissions?: { __typename?: 'AppStoreConnectApiKey', id: string, issuerIdentifier: string, keyIdentifier: string, name?: string | null, roles?: Array<AppStoreConnectUserRole> | null, createdAt: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null } | null }> } } };
export type CreateAppMutationVariables = Exact<{
appInput: AppInput;
@@ -6247,14 +6513,14 @@ export type AppByIdQueryVariables = Exact<{
}>;
export type AppByIdQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } } } };
export type AppByIdQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __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 AppByFullNameQueryVariables = Exact<{
fullName: Scalars['String'];
}>;
export type AppByFullNameQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byFullName: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } } } };
export type AppByFullNameQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byFullName: { __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 LatestAppVersionQueryVariables = Exact<{
appId: Scalars['String'];
@@ -6334,7 +6600,7 @@ export type ViewUpdateChannelOnAppQueryVariables = Exact<{
}>;
export type ViewUpdateChannelOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateChannelByName?: { __typename?: 'UpdateChannel', id: string, name: string, createdAt: any, branchMapping: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null }>> }> } | null } } };
export type ViewUpdateChannelOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateChannelByName?: { __typename?: 'UpdateChannel', id: string, name: string, updatedAt: any, createdAt: any, branchMapping: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null }>> }> } | null } } };
export type ViewUpdateChannelsOnAppQueryVariables = Exact<{
appId: Scalars['String'];
@@ -6343,7 +6609,7 @@ export type ViewUpdateChannelsOnAppQueryVariables = Exact<{
}>;
export type ViewUpdateChannelsOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateChannels: Array<{ __typename?: 'UpdateChannel', id: string, name: string, createdAt: any, branchMapping: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null }>> }> }> } } };
export type ViewUpdateChannelsOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateChannels: Array<{ __typename?: 'UpdateChannel', id: string, name: string, updatedAt: any, createdAt: any, branchMapping: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null }>> }> }> } } };
export type ViewUpdateChannelsPaginatedOnAppQueryVariables = Exact<{
appId: Scalars['String'];
@@ -6446,7 +6712,7 @@ export type ViewUpdateGroupsOnAppQuery = { __typename?: 'RootQuery', app: { __ty
export type CurrentUserQueryVariables = Exact<{ [key: string]: never; }>;
export type CurrentUserQuery = { __typename?: 'RootQuery', meActor?: { __typename: 'Robot', firstName?: string | null, id: string, featureGates: any, isExpoAdmin: boolean, accounts: Array<{ __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }> } | { __typename: 'SSOUser', username: string, id: string, featureGates: any, isExpoAdmin: boolean, primaryAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }, accounts: Array<{ __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }> } | { __typename: 'User', username: string, id: string, featureGates: any, isExpoAdmin: boolean, primaryAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }, accounts: Array<{ __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }> } | null };
export type CurrentUserQuery = { __typename?: 'RootQuery', meActor?: { __typename: 'Robot', firstName?: string | null, id: string, featureGates: any, isExpoAdmin: boolean, accounts: Array<{ __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 } }> }> } | { __typename: 'SSOUser', username: string, id: string, featureGates: any, isExpoAdmin: boolean, primaryAccount: { __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 } }> }, accounts: Array<{ __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 } }> }> } | { __typename: 'User', username: string, id: string, featureGates: any, isExpoAdmin: boolean, primaryAccount: { __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 } }> }, accounts: Array<{ __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 } }> }> } | null };
export type WebhooksByAppIdQueryVariables = Exact<{
appId: Scalars['String'];
@@ -6463,9 +6729,9 @@ export type WebhookByIdQueryVariables = Exact<{
export type WebhookByIdQuery = { __typename?: 'RootQuery', webhook: { __typename?: 'WebhookQuery', byId: { __typename?: 'Webhook', id: string, event: WebhookType, url: string, createdAt: any, updatedAt: any } } };
export type AccountFragment = { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> };
export type AccountFragment = { __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 AppFragment = { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: 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 } | 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 } };
@@ -6491,7 +6757,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, 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, 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 } };
@@ -6501,24 +6767,24 @@ export type AppStoreConnectApiKeyFragment = { __typename?: 'AppStoreConnectApiKe
export type AppleAppIdentifierFragment = { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string };
export type AppleDeviceFragment = { __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null };
export type AppleDeviceFragment = { __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt?: any | null };
export type AppleDeviceRegistrationRequestFragment = { __typename?: 'AppleDeviceRegistrationRequest', id: string };
export type AppleDistributionCertificateFragment = { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> };
export type AppleDistributionCertificateFragment = { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> };
export type AppleProvisioningProfileFragment = { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null }> };
export type AppleProvisioningProfileFragment = { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt?: any | null }> };
export type AppleProvisioningProfileIdentifiersFragment = { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null };
export type ApplePushKeyFragment = { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> };
export type ApplePushKeyFragment = { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> };
export type AppleTeamFragment = { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null };
export type GoogleServiceAccountKeyFragment = { __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any };
export type IosAppBuildCredentialsFragment = { __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null }> } | null };
export type IosAppBuildCredentialsFragment = { __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt?: any | null }> } | null };
export type CommonIosAppCredentialsWithoutBuildCredentialsFragment = { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string }, pushKey?: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } | null, appStoreConnectApiKeyForSubmissions?: { __typename?: 'AppStoreConnectApiKey', id: string, issuerIdentifier: string, keyIdentifier: string, name?: string | null, roles?: Array<AppStoreConnectUserRole> | null, createdAt: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null } | null };
export type CommonIosAppCredentialsWithoutBuildCredentialsFragment = { __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string }, pushKey?: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } | null, appStoreConnectApiKeyForSubmissions?: { __typename?: 'AppStoreConnectApiKey', id: string, issuerIdentifier: string, keyIdentifier: string, name?: string | null, roles?: Array<AppStoreConnectUserRole> | null, createdAt: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null } | null };
export type CommonIosAppCredentialsFragment = { __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null }> } | null }>, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string }, pushKey?: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } | null, appStoreConnectApiKeyForSubmissions?: { __typename?: 'AppStoreConnectApiKey', id: string, issuerIdentifier: string, keyIdentifier: string, name?: string | null, roles?: Array<AppStoreConnectUserRole> | null, createdAt: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null } | null };
export type CommonIosAppCredentialsFragment = { __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt?: any | null }> } | null }>, 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 } }> } }, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string }, pushKey?: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, 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 } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } | null, appStoreConnectApiKeyForSubmissions?: { __typename?: 'AppStoreConnectApiKey', id: string, issuerIdentifier: string, keyIdentifier: string, name?: string | null, roles?: Array<AppStoreConnectUserRole> | null, createdAt: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null } | null };
@@ -60,6 +60,7 @@ export const ChannelQuery = {
updateChannelByName(name: $channelName) {
id
name
updatedAt
createdAt
branchMapping
updateBranches(offset: 0, limit: 5) {
@@ -104,6 +105,7 @@ export const ChannelQuery = {
updateChannels(offset: $offset, limit: $limit) {
id
name
updatedAt
createdAt
branchMapping
updateBranches(offset: 0, limit: 5) {
@@ -4,6 +4,10 @@ export const AccountFragmentNode = gql`
fragment AccountFragment on Account {
id
name
ownerUserActor {
id
username
}
users {
actor {
id
@@ -15,5 +15,6 @@ export const AppleDeviceFragmentNode = gql`
name
model
deviceClass
createdAt
}
`;
+4
View File
@@ -57,6 +57,10 @@ export default class Log {
Log.consoleLog(chalk.green(figures.tick), ...args);
}
public static withInfo(...args: any[]): void {
Log.consoleLog(chalk.green(figures.info), ...args);
}
private static consoleLog(...args: any[]): void {
Log.updateIsLastLineNewLine(args);
// eslint-disable-next-line no-console
+11 -4
View File
@@ -6,6 +6,7 @@ import assert from 'assert';
import { CredentialsContext } from '../credentials/context';
import { getRequestContext } from '../credentials/ios/appstore/authenticate';
import { getBundleIdentifierAsync } from '../project/ios/bundleIdentifier';
import { Client } from '../vcs/vcs';
export type MetadataAppStoreAuthentication = {
/** The root entity of the App store */
@@ -21,13 +22,14 @@ export type MetadataAppStoreAuthentication = {
async function resolveAppStoreBundleIdentifierAsync(
projectDir: string,
profile: SubmitProfile,
exp: ExpoConfig
exp: ExpoConfig,
vcsClient: Client
): Promise<string> {
if ('bundleIdentifier' in profile) {
return profile.bundleIdentifier ?? (await getBundleIdentifierAsync(projectDir, exp));
return profile.bundleIdentifier ?? (await getBundleIdentifierAsync(projectDir, exp, vcsClient));
}
return await getBundleIdentifierAsync(projectDir, exp);
return await getBundleIdentifierAsync(projectDir, exp, vcsClient);
}
/**
@@ -45,7 +47,12 @@ export async function getAppStoreAuthAsync({
exp: ExpoConfig;
credentialsCtx: CredentialsContext;
}): Promise<MetadataAppStoreAuthentication> {
const bundleId = await resolveAppStoreBundleIdentifierAsync(projectDir, profile, exp);
const bundleId = await resolveAppStoreBundleIdentifierAsync(
projectDir,
profile,
exp,
credentialsCtx.vcsClient
);
const authCtx = await credentialsCtx.appStore.ensureAuthenticatedAsync();
assert(authCtx.authState, 'Failed to authenticate with App Store Connect');
@@ -0,0 +1,68 @@
import { AppJSONConfig, PackageJSONConfig } from '@expo/config';
import { vol } from 'memfs';
import path from 'path';
import resolveFrom from 'resolve-from';
import { enforceRollBackToEmbeddedUpdateSupportAsync } from '../projectUtils';
jest.mock('fs');
jest.mock('resolve-from');
const projectRoot = '/test-project';
describe(enforceRollBackToEmbeddedUpdateSupportAsync, () => {
it('does not throw when an appropriate version is installed', async () => {
mockTestProject('0.19.1');
await enforceRollBackToEmbeddedUpdateSupportAsync(projectRoot);
});
it('throws when an unappropriate version is installed', async () => {
mockTestProject('0.18.0');
await expect(enforceRollBackToEmbeddedUpdateSupportAsync(projectRoot)).rejects.toThrowError(
'The expo-updates package must have a version >= 0.19.0 to use roll back to embedded, which corresponds to Expo SDK 50 or greater.'
);
});
});
function mockTestProject(expoUpdatesPackageVersion: string): { appJson: AppJSONConfig } {
const packageJSON: PackageJSONConfig = {
name: 'testing123',
version: '0.1.0',
description: 'fake description',
main: 'index.js',
dependencies: {
'expo-updates': expoUpdatesPackageVersion,
},
};
const expoUpdatesPackageJSON: PackageJSONConfig = {
name: 'expo-updates',
version: expoUpdatesPackageVersion,
};
const appJSON: AppJSONConfig = {
expo: {
name: 'testing 123',
version: '0.1.0',
slug: 'testing-123',
sdkVersion: '33.0.0',
},
};
jest
.mocked(resolveFrom.silent)
.mockReturnValue(path.join(projectRoot, 'node_modules/expo-updates/package.json'));
vol.fromJSON(
{
'package.json': JSON.stringify(packageJSON),
'app.json': JSON.stringify(appJSON),
'node_modules/expo-updates/package.json': JSON.stringify(expoUpdatesPackageJSON),
},
projectRoot
);
return { appJson: appJSON };
}
@@ -576,6 +576,7 @@ describe(uploadAssetsAsync, () => {
assetsForUpdateInfoGroup,
testProjectId,
{ isCanceledOrFinished: false },
() => {},
() => {}
)
).resolves.toEqual({
@@ -622,6 +623,7 @@ describe(uploadAssetsAsync, () => {
{
isCanceledOrFinished: false,
},
() => {},
() => {}
)
).resolves.toEqual({
@@ -667,7 +669,8 @@ describe(uploadAssetsAsync, () => {
assetsForUpdateInfoGroup,
testProjectId,
{ isCanceledOrFinished: false },
onAssetUploadResultsChangedFn
onAssetUploadResultsChangedFn,
() => {}
);
expect(onAssetUploadResultsChangedFn).toHaveBeenCalledTimes(3);
});
@@ -1,11 +1,13 @@
import { Platform, Workflow } from '@expo/eas-build-job';
import { vol } from 'memfs';
import { getVcsClient } from '../../vcs';
import { resolveWorkflowAsync, resolveWorkflowPerPlatformAsync } from '../workflow';
jest.mock('fs');
const projectDir = '/app';
const vcsClient = getVcsClient();
describe(resolveWorkflowAsync, () => {
beforeEach(() => {
@@ -21,10 +23,12 @@ describe(resolveWorkflowAsync, () => {
projectDir
);
await expect(resolveWorkflowAsync(projectDir, Platform.ANDROID)).resolves.toBe(
await expect(resolveWorkflowAsync(projectDir, Platform.ANDROID, vcsClient)).resolves.toBe(
Workflow.GENERIC
);
await expect(resolveWorkflowAsync(projectDir, Platform.IOS, vcsClient)).resolves.toBe(
Workflow.GENERIC
);
await expect(resolveWorkflowAsync(projectDir, Platform.IOS)).resolves.toBe(Workflow.GENERIC);
});
test('bare workflow for single platform', async () => {
@@ -35,10 +39,12 @@ describe(resolveWorkflowAsync, () => {
projectDir
);
await expect(resolveWorkflowAsync(projectDir, Platform.ANDROID)).resolves.toBe(
await expect(resolveWorkflowAsync(projectDir, Platform.ANDROID, vcsClient)).resolves.toBe(
Workflow.MANAGED
);
await expect(resolveWorkflowAsync(projectDir, Platform.IOS)).resolves.toBe(Workflow.GENERIC);
await expect(resolveWorkflowAsync(projectDir, Platform.IOS, vcsClient)).resolves.toBe(
Workflow.GENERIC
);
});
test('android/ios directories are ignored', async () => {
@@ -51,10 +57,12 @@ describe(resolveWorkflowAsync, () => {
projectDir
);
await expect(resolveWorkflowAsync(projectDir, Platform.ANDROID)).resolves.toBe(
await expect(resolveWorkflowAsync(projectDir, Platform.ANDROID, vcsClient)).resolves.toBe(
Workflow.MANAGED
);
await expect(resolveWorkflowAsync(projectDir, Platform.IOS, vcsClient)).resolves.toBe(
Workflow.MANAGED
);
await expect(resolveWorkflowAsync(projectDir, Platform.IOS)).resolves.toBe(Workflow.MANAGED);
});
});
@@ -72,7 +80,7 @@ describe(resolveWorkflowPerPlatformAsync, () => {
projectDir
);
await expect(resolveWorkflowPerPlatformAsync(projectDir)).resolves.toEqual({
await expect(resolveWorkflowPerPlatformAsync(projectDir, vcsClient)).resolves.toEqual({
android: Workflow.GENERIC,
ios: Workflow.GENERIC,
});
@@ -7,6 +7,7 @@ import { ExpoGraphqlClient } from '../../../commandUtils/context/contextUtils/cr
import { jester, jester as mockJester } from '../../../credentials/__tests__/fixtures-constants';
import { AppQuery } from '../../../graphql/queries/AppQuery';
import { promptAsync } from '../../../prompts';
import { getVcsClient } from '../../../vcs';
import {
ensureApplicationIdIsDefinedForManagedProjectAsync,
getApplicationIdAsync,
@@ -17,6 +18,8 @@ jest.mock('../../../prompts');
jest.mock('../../../graphql/queries/AppQuery');
jest.mock('../../../user/actions', () => ({ ensureLoggedInAsync: jest.fn(() => mockJester) }));
const vcsClient = getVcsClient();
beforeEach(async () => {
vol.reset();
@@ -44,7 +47,9 @@ describe(getApplicationIdAsync, () => {
'/app'
);
const applicationId = await getApplicationIdAsync('/app', {} as any, { moduleName: 'app' });
const applicationId = await getApplicationIdAsync('/app', {} as any, vcsClient, {
moduleName: 'app',
});
expect(applicationId).toBe('com.expo.notdominik');
});
@@ -56,9 +61,9 @@ describe(getApplicationIdAsync, () => {
},
'/app'
);
await expect(getApplicationIdAsync('/app', {} as any, undefined)).rejects.toThrowError(
/Failed to find 'build.gradle' /
);
await expect(
getApplicationIdAsync('/app', {} as any, vcsClient, undefined)
).rejects.toThrowError(/Failed to find 'build.gradle' /);
});
it('throws an error if the project does not have applicationId defined in build.gradle', async () => {
@@ -71,7 +76,7 @@ describe(getApplicationIdAsync, () => {
);
await expect(
getApplicationIdAsync('/app', {} as any, { moduleName: 'app' })
getApplicationIdAsync('/app', {} as any, vcsClient, { moduleName: 'app' })
).rejects.toThrowError(/Could not read applicationId/);
});
});
@@ -83,6 +88,7 @@ describe(getApplicationIdAsync, () => {
{
android: { package: 'com.expo.notdominik' },
} as any,
vcsClient,
{ moduleName: 'app' }
);
expect(applicationId).toBe('com.expo.notdominik');
@@ -90,15 +96,20 @@ describe(getApplicationIdAsync, () => {
it('throws an error if Android package is not defined in app config', async () => {
await expect(
getApplicationIdAsync('/app', {} as any, { moduleName: 'app' })
getApplicationIdAsync('/app', {} as any, vcsClient, { moduleName: 'app' })
).rejects.toThrowError(/Specify "android.package"/);
});
it('throws an error if Android package in app config is invalid', async () => {
await expect(
getApplicationIdAsync('/app', { android: { package: '1com.expo.notdominik' } } as any, {
moduleName: 'app',
})
getApplicationIdAsync(
'/app',
{ android: { package: '1com.expo.notdominik' } } as any,
vcsClient,
{
moduleName: 'app',
}
)
).rejects.toThrowError(/Specify "android.package"/);
});
});
@@ -121,6 +132,7 @@ describe(ensureApplicationIdIsDefinedForManagedProjectAsync, () => {
projectDir: '/app',
projectId: '',
exp: {} as any,
vcsClient,
})
).rejects.toThrowError(/we can't update this file programmatically/);
});
@@ -150,6 +162,7 @@ describe(ensureApplicationIdIsDefinedForManagedProjectAsync, () => {
projectDir: '/app',
projectId: '',
exp: {} as any,
vcsClient,
})
).resolves.toBe('com.expo.notdominik');
expect(promptAsync).toHaveBeenCalled();
@@ -182,6 +195,7 @@ describe(ensureApplicationIdIsDefinedForManagedProjectAsync, () => {
projectDir: '/app',
projectId: '',
exp: {} as any,
vcsClient,
})
).resolves.toBe('com.expo.notdominik');
const appJson = JSON.parse(await fs.readFile('/app/app.json', 'utf-8'));
@@ -4,12 +4,15 @@ import os from 'os';
import { jester as mockJester } from '../../../credentials/__tests__/fixtures-constants';
import { promptAsync } from '../../../prompts';
import { getVcsClient } from '../../../vcs';
import { resolveGradleBuildContextAsync } from '../gradle';
jest.mock('fs');
jest.mock('../../../prompts');
jest.mock('../../../user/actions', () => ({ ensureLoggedInAsync: jest.fn(() => mockJester) }));
const vcsClient = getVcsClient();
beforeEach(async () => {
vol.reset();
// do not remove the following line
@@ -36,7 +39,7 @@ describe(resolveGradleBuildContextAsync, () => {
'/app'
);
const gradleContext = await resolveGradleBuildContextAsync('/app', {} as any);
const gradleContext = await resolveGradleBuildContextAsync('/app', {} as any, vcsClient);
expect(gradleContext).toEqual({ moduleName: 'app' });
});
it('resolves to flavor', async () => {
@@ -59,9 +62,13 @@ describe(resolveGradleBuildContextAsync, () => {
'/app'
);
const gradleContext = await resolveGradleBuildContextAsync('/app', {
gradleCommand: ':app:buildAbcRelease',
} as any);
const gradleContext = await resolveGradleBuildContextAsync(
'/app',
{
gradleCommand: ':app:buildAbcRelease',
} as any,
vcsClient
);
expect(gradleContext).toEqual({ moduleName: 'app', flavor: 'abc' });
});
@@ -73,9 +80,13 @@ describe(resolveGradleBuildContextAsync, () => {
},
'/app'
);
const gradleContext = await resolveGradleBuildContextAsync('/app', {
gradleCommand: ':app:buildAbcRelease',
} as any);
const gradleContext = await resolveGradleBuildContextAsync(
'/app',
{
gradleCommand: ':app:buildAbcRelease',
} as any,
vcsClient
);
expect(gradleContext).toEqual(undefined);
});
it('returns undefined if flavor does not exist', async () => {
@@ -93,16 +104,20 @@ describe(resolveGradleBuildContextAsync, () => {
'/app'
);
const gradleContext = await resolveGradleBuildContextAsync('/app', {
gradleCommand: ':app:buildAbcRelease',
} as any);
const gradleContext = await resolveGradleBuildContextAsync(
'/app',
{
gradleCommand: ':app:buildAbcRelease',
} as any,
vcsClient
);
expect(gradleContext).toEqual(undefined);
});
});
describe('managed projects', () => {
it('resolves to { moduleName: app } for managed projects', async () => {
const gradleContext = await resolveGradleBuildContextAsync('/app', {} as any);
const gradleContext = await resolveGradleBuildContextAsync('/app', {} as any, {} as any);
expect(gradleContext).toEqual({ moduleName: 'app' });
});
});
@@ -15,6 +15,7 @@ import {
getProjectConfigDescription,
} from '../../project/projectUtils';
import { promptAsync } from '../../prompts';
import { Client } from '../../vcs/vcs';
import { resolveWorkflowAsync } from '../workflow';
import { GradleBuildContext } from './gradle';
import * as gradleUtils from './gradleUtils';
@@ -26,17 +27,19 @@ export async function ensureApplicationIdIsDefinedForManagedProjectAsync({
projectDir,
projectId,
exp,
vcsClient,
}: {
graphqlClient: ExpoGraphqlClient;
projectDir: string;
projectId: string;
exp: ExpoConfig;
vcsClient: Client;
}): Promise<string> {
const workflow = await resolveWorkflowAsync(projectDir, Platform.ANDROID);
const workflow = await resolveWorkflowAsync(projectDir, Platform.ANDROID, vcsClient);
assert(workflow === Workflow.MANAGED, 'This function should be called only for managed projects');
try {
return await getApplicationIdAsync(projectDir, exp, {
return await getApplicationIdAsync(projectDir, exp, vcsClient, {
moduleName: gradleUtils.DEFAULT_MODULE_NAME,
});
} catch {
@@ -95,9 +98,10 @@ export async function getApplicationIdFromBareAsync(
export async function getApplicationIdAsync(
projectDir: string,
exp: ExpoConfig,
vcsClient: Client,
gradleContext?: GradleBuildContext
): Promise<string> {
const workflow = await resolveWorkflowAsync(projectDir, Platform.ANDROID);
const workflow = await resolveWorkflowAsync(projectDir, Platform.ANDROID, vcsClient);
if (workflow === Workflow.GENERIC) {
warnIfAndroidPackageDefinedInAppConfigForBareWorkflowProject(projectDir, exp);
Loaded 100 of 146 files, more files were not shown because too many files have changed in this diff. Show more