Compare commits

...
59 Commits
Author SHA1 Message Date
Dominik Sokal 2232a5ed59 v3.4.0 2023-01-20 13:51:06 +01:00
Dominik Sokal ef3e9079e5 [ENG-7283] add a prompt to switch iOS builds to M1 if queue is long (#1642)
* add a prompt to switch iOS builds to M1 if queue is long

* update CHANGELOG.md
2023-01-20 13:46:46 +01:00
Wojciech Kozyra ec10eff1e6 [eas-cli] Print warning about EAS_NO_VCS option to stderr (#1641)
* [eas-cli] Print warning about EAS_NO_VCS option to stderr

* update CHANGELOG.md
2023-01-20 11:31:50 +01:00
Szymon Dziedzic 3e3ec87622 [ENG-7223][ci] run tests on each changelog workflow automated commit (#1640)
* [ci] add test changelog workflow

* update main changelog workflow

* delete changelog_2 workflow

* use correct command

* select last commit author as automated changelog change author
2023-01-20 11:01:12 +01:00
Wojciech Kozyra f1cf92d63a [eas-cli] Print error message sent from server (#1639) 2023-01-19 14:17:59 +01:00
Brent Vatne 7096daa116 [eas-cli] Switch to using M1 by default when running build:configure (#1637) 2023-01-18 11:35:24 -08:00
Dominik Sokal 6429e70a9a print disabled resource class labels (#1635)
* print disabled resource class labels

* update CHANGELOG.md
2023-01-18 18:26:21 +01:00
Wojciech Kozyra 083381da82 [eas-cli] Automatically promote new cli release to staging on EAS Build (#1624) 2023-01-16 10:08:46 +01:00
Dominik Sokal 1c1af2da86 remove nx and upgrade lerna (https://github.com/lerna/lerna/pull/3495) 2023-01-13 10:40:06 +01:00
Wojciech Kozyra 72ce75e1ee [eas-cli] Base implementation for running builds directly from GitHub (#1568) 2023-01-13 10:01:53 +01:00
Wojciech Kozyra ea553a1025 [eas-cli] Remove workaround for gitignore with trailing backslash (#1622)
* [eas-cli] Remove workaround (fixed upstream)

* update CHANGELOG.md
2023-01-12 15:27:23 +01:00
Expo CI 3a6bcb3f2e update CHANGELOG.md 2023-01-12 11:06:59 +00:00
Dominik Sokal 8b27255ce2 v3.3.2 2023-01-12 11:59:22 +01:00
Szymon Dziedzic 1f0ae27ea0 [eas-cli] improve handling SSOUser type (#1621)
* [eas-cli] improve handling SSOUser type

* update CHANGELOG.md
2023-01-12 11:53:45 +01:00
Dominik Sokal 62d26ca32b add nx to root deps 2023-01-12 11:22:44 +01:00
Dominik Sokal 3aebb54d11 upgrade dependencies (#1617)
* upgrade dependencies

* fixes

* fix types

* update CHANGELOG.md
2023-01-12 10:26:23 +01:00
Cedric van Putten 0bf42e4cd4 [eas-cli] Add missing key information about updates in json outputs (#1619)
* Revert "Revert "[eas-cli] Add missing key information about updates in json outputs (#1611)""

This reverts commit d20db0fff4.

* [eas-cli] Fix missing update fragment in publish mutation

* [docs] Update changelog to reflect the revert and new entry
2023-01-12 10:06:48 +01:00
Expo CI ec4ef42f3c update CHANGELOG.md 2023-01-11 22:25:41 +00:00
James Ide a70222d35d v3.3.1 2023-01-11 14:18:03 -08:00
James Ide d20db0fff4 Revert "[eas-cli] Add missing key information about updates in json outputs (#1611)"
Why
---
This reverts commit e42031eaef. A customer reported an issue with publishing updates.

How
---
Ran `git revert` and then re-generated the GraphQL schemas due to merge conflicts using `yarn generate-graphql-code`.

Test Plan
---
Automated tests. Ran `easd update --auto` in a test project.
2023-01-11 12:43:35 -08:00
Expo CI 00ef6087f8 update CHANGELOG.md 2023-01-11 16:22:58 +00:00
Szymon Dziedzic 9c74c5c6b8 v3.3.0 2023-01-11 16:52:32 +01:00
Szymon Dziedzic 719febc519 [ENG-7158][ENG-7060][eas-cli][eas-json] handle new resource class names (#1616)
* [eas-cli][eas-json] handle new resource classes in EAS CLI

* show warning for large iOS resource classes

* don't deprecate resource class flag in this PR

* apply suggested improvements

* fix markdown description of top level resource class

* fix large resource class warning

* update CHANGELOG.md

* update eas.schema.json

* improve eas.schema.json

* add support for medium resource class and update eas.json

* fix error message for large resource classes

* temporary changes to solve issues with SSOUser being added to schema

* fix tests

* fix error message

* remove unnecessary dot

* update changelog
2023-01-11 16:47:37 +01:00
Dominik Sokal 9d9c99c0f6 [ENG-7198][build] deprecate --resource-class flag (#1615)
* [build] deprecate --resource-class flag

* address PR feedback
2023-01-11 10:18:08 +01:00
Cedric van Putten e42031eaef [eas-cli] Add missing key information about updates in json outputs (#1611)
* [eas-cli] Add missing key information about updates in json outputs

* [eas-cli] Fix linting issue

* [eas-cli] Fix update command tests with new types

* [eas-cli] Emphasize the update JSON output helper provides info for JSON output

* update CHANGELOG.md
2023-01-09 05:44:33 -08:00
Dominik Sokal 9ec43bce84 [ENG-7158] add resource class to eas.json (#1609)
* add resource class to eas.json

* address PR feedback
2023-01-09 14:22:56 +01:00
Expo CI 488c3b3cb8 update CHANGELOG.md 2023-01-09 13:08:30 +00:00
Szymon Dziedzic f5ac3d26a0 v3.2.1 2023-01-09 14:01:21 +01:00
Szymon Dziedzic 6be86d5119 [eas-cli] validate chosen build in eas build:run command (#1614)
* [eas-cli] throw error when there are no emulator/simulator builds in `eas build:run` command

* handle missing build in correct place

* handle same error for latest flag

* add function to sanitize chosen build

* sanitize build selected by id

* improve build santization

* apply suggested improvements

* rename validation function

* update CHANGELOG.md
2023-01-09 14:00:30 +01:00
dependabot[bot] 04025802ac Bump json5 from 1.0.1 to 1.0.2 (#1610)
Bumps [json5](https://github.com/json5/json5) from 1.0.1 to 1.0.2.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](https://github.com/json5/json5/compare/v1.0.1...v1.0.2)

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

Signed-off-by: dependabot[bot] <[email protected]>

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-09 11:37:25 +01:00
Expo CI 0a4c8785e6 update CHANGELOG.md 2023-01-09 09:51:36 +00:00
Szymon Dziedzic 1de239b6ba v3.2.0 2023-01-09 10:45:11 +01:00
Simon Blake 4515d29907 Add --json flag to webhook:list command (#1605) 2023-01-04 13:41:10 +01:00
Szymon Dziedzic 7591cac883 [ENG-7069][eas-cli] Use pagianted select prompt for eas build:run command (#1601)
* [eas-cli] Use pagianted select prompt for eas build:run command

* apply suggestions from code review

* apply improvements from code review

* update CHANGELOG.md
2023-01-04 11:32:17 +01:00
Szymon Dziedzic 9765f75a7d [eas-cli] use completedAt timestamp as build finish date instead of updatedAt in eas build:run command (#1604)
* [eas-cli] use `completedAt` timestamp as build finish date instead of `updatedAt` in `eas build:run` command

* update CHANGELOG.md
2023-01-04 11:22:10 +01:00
Szymon Dziedzic 1f1b58db82 [ENG-7070][eas-cli] fix issues with invisible build info in some terminals while using submit command (#1603)
* [eas-cli] fix issues with invisible build info in some terminals while using submit command

* update CHANGELOG.md
2023-01-04 11:18:10 +01:00
Bartosz KaszubowskiandDominik Sokal b0c88a37a9 [eas-cli] ensure that all links are clickable, unify display (#1591)
Co-authored-by: Dominik Sokal <[email protected]>
2023-01-04 11:09:35 +01:00
Jon Samp 5694bb9fdc [eas-cli] Makes eas.json configuration to only run on update:configure (#1598)
* Makes eas.json configuration to only run on update:configure

* update CHANGELOG.md
2023-01-03 22:37:49 -06:00
Szymon Dziedzic 9245657e23 [ENG-7070][eas-cli] Fix issues with invisible build info in some terminals in build:run and build:resign commands (#1602)
* [eas-cli] Fix issues with invisible build info in some terminals

* update CHANGELOG.md
2023-01-03 13:41:25 +01:00
Jon Samp 9ef8483882 [eas-cli] use appVersion instead of sdkVersion (#1588)
* use appVersion instead of sdkVersion

* update CHANGELOG.md
2022-12-29 00:00:23 -06:00
Dominik Sokal b859e11126 update CONTRIBUTING.md + add RELEASING.md (#1583)
* update CONTRIBUTING.md

* address PR feedback
2022-12-21 11:48:55 +01:00
James Ide cee499e0e6 [ui] Rename "queue" to "Free tier queue" (#1582) 2022-12-20 15:17:28 -08:00
Cedric van Putten 8702f165f3 [eas-cli] Add --channel to update republish (#1580)
* [eas-cli] Add test cases for republishing updates

* [eas-cli] Tweak the channel -> branch method errors to reuse in republish

* [eas-cli] Add support for --channel in update:republish

* [eas-cli] Add test cases to prevent using --group, --channel, or --branch together

* update CHANGELOG.md

* [eas-cli] Update the test case for resolving branch from channel
2022-12-19 22:35:14 +01:00
Cedric van Putten a6bea7e234 [eas-cli] Increase the timeout for loading the command config (#1581) 2022-12-19 21:47:13 +01:00
Expo CI 37343dd586 update CHANGELOG.md 2022-12-19 16:24:12 +00:00
Cedric van Putten 058183f202 v3.1.1 2022-12-19 16:57:33 +01:00
Cedric van Putten 7ee50de78e [eas-cli] Fix update --channel and --branch flag validation (#1579)
* [eas-cli] Add initial test cases for the update command

* [eas-cli] Add runtimeVersion option when mocking exports

* [eas-cli] Fix update flag validation for --branch and --channel

* [eas-cli] Add test case for --non-interactive, --channel, and --message

* update CHANGELOG.md

* [eas-cli] Fix linting issue

* [eas-cli] Reuse the input dir from the command

* [eas-cli] Explicitly mention the allowed flag combinations to avoid ambiguity

* [eas-cli] Move --auto to a distinct location in the error message

* [eas-cli] Fix linting issue
2022-12-19 16:36:18 +01:00
Expo CI ca11aa9e41 update CHANGELOG.md 2022-12-17 00:00:52 +00:00
Brent Vatne 64d985fcda v3.1.0 2022-12-16 15:54:02 -08:00
Jon Samp bd2bb4dcf6 [eas-cli] Add --channel flag to eas update command (#1567)
* Add --channel flag to eas update command

* use existing method

* adds undefined to return type

* move to getBranchNameFromChannelNameAsync.ts

* renames the function to singular "update"
2022-12-15 10:56:30 -06:00
Wojciech Kozyra 17db6c4cf1 [eas-cli] Add build:resign command (#1575) 2022-12-15 14:23:10 +01:00
Jon SampandDominik Sokal 5203096aca [eas-cli] Adds channels to build profiles on eas update:configure (#1570)
* Adds eas.json configuration during eas update configure

* updates next steps message

* renames eas updates to eas update

* self feedback

* update CHANGELOG.md

* Update packages/eas-cli/src/commands/update/configure.ts

Co-authored-by: Dominik Sokal <[email protected]>

* Update packages/eas-cli/src/commands/update/configure.ts

Co-authored-by: Dominik Sokal <[email protected]>

* code style feedback incorp

* use EasJsonAccessor

* Update packages/eas-cli/src/update/configure.ts

Co-authored-by: Dominik Sokal <[email protected]>

* lint

Co-authored-by: Dominik Sokal <[email protected]>
2022-12-12 10:59:41 -06:00
Expo CI a53e1f916f update CHANGELOG.md 2022-12-07 10:15:44 +00:00
Szymon Dziedzic 09a4b3d387 v3.0.0 2022-12-07 11:01:22 +01:00
Szymon Dziedzic 24e7de5bfb [eas-cli] Fix eas cli node:assert import error by using imports from assert instead of node:assert (#1569)
* [eas-cli] use import from 'assert' instead from 'node:assert'

* update CHANGELOG.md
2022-12-07 10:57:45 +01:00
Szymon Dziedzic 613fb5b6ea [eas-json] Make not recognized image error handler run only if image is present under valid key with invalid value (#1565)
* [eas-json] Make not recognized image error handler fire only if image is present under valid key with invalid value

* revert changes to error message

* update CHANGELOG.md
2022-12-06 14:08:03 +01:00
Cedric van Putten 4e117075fa refactor(update): remove republish from update command (#1535)
* fix(update): add code signing support to republish and block different branches

* refactor(update): move codesigning info into update fragment

* update CHANGELOG.md

* fix(update): add code signing support to republish and block different branches

* refactor(update): mark group and republish flags as deprecated

* refactor(update): drop republish and group flags

* refactor(update): drop republish flag from command

* refactor(update): remove last republish code from update command

* refactor(update): either use --group or --branch in deprecation warning

* refactor(update): drop old runtime version from update command

* refactor(update): move asset variables closer to populated area

* fix(update): fix republish typo in deprecation warning

* fix(update): correct a merge conflict error related to publish query changes
2022-12-05 13:25:52 +01:00
Cedric van Putten 33f4ae7a05 [eas-cli] Split republish command from update command (#1533)
* refactor(update): split out republish to separate command

* fix(update): add code signing support to republish and block different branches

* test(update): add missing republish command tests

* test(update): add test case without codesigning

* refactor(update): move codesigning info into update fragment

* refactor(update): make branch and group exclusive and simplify code

* update CHANGELOG.md
2022-12-05 04:08:56 -08:00
Expo CI caba28901d update CHANGELOG.md 2022-12-05 12:03:51 +00:00
85 changed files with 9068 additions and 4132 deletions

No files matched your search

+2
View File
@@ -10,6 +10,8 @@ jobs:
if: ${{ github.event.issue.pull_request && github.event.issue.user.login == github.event.comment.user.login && startsWith(github.event.comment.body, '/changelog-entry ') }}
steps:
- uses: actions/checkout@v2
with:
token: ${{ secrets.EXPO_BOT_PAT }}
- uses: actions/setup-node@v2
with:
node-version: 18
+13 -5
View File
@@ -36,10 +36,10 @@ jobs:
yarn pretarball-ci
yarn oclif pack:tarballs --no-xz --targets linux-x64,linux-arm
- id: x64
run: echo "::set-output name=filename::$(ls eas-*-x64.tar.gz)"
run: echo "filename=$(ls eas-*-x64.tar.gz)" >> $GITHUB_OUTPUT
working-directory: ${{ github.workspace }}/packages/eas-cli/dist
- id: arm
run: echo "::set-output name=filename::$(ls eas-*-arm.tar.gz)"
run: echo "filename=$(ls eas-*-arm.tar.gz)" >> $GITHUB_OUTPUT
working-directory: ${{ github.workspace }}/packages/eas-cli/dist
- name: Upload linux-x64 tarball
uses: actions/upload-release-asset@v1
@@ -77,7 +77,7 @@ jobs:
yarn pretarball-ci
yarn oclif pack:tarballs --no-xz --targets darwin-x64
- id: x64
run: echo "::set-output name=filename::$(ls eas-*-x64.tar.gz)"
run: echo "filename=$(ls eas-*-x64.tar.gz)" >> $GITHUB_OUTPUT
working-directory: ${{ github.workspace }}/packages/eas-cli/dist
- name: Upload darwin-x64 tarball
uses: actions/upload-release-asset@v1
@@ -105,10 +105,10 @@ jobs:
yarn oclif pack:win
working-directory: ${{ github.workspace }}/packages/eas-cli
- id: x64
run: echo "::set-output name=filename::$(ls eas-*-x64.exe)"
run: echo "filename=$(ls eas-*-x64.exe)" >> $GITHUB_OUTPUT
working-directory: ${{ github.workspace }}/packages/eas-cli/dist/win32
- id: x86
run: echo "::set-output name=filename::$(ls eas-*-x86.exe)"
run: echo "filename=$(ls eas-*-x86.exe)" >> $GITHUB_OUTPUT
working-directory: ${{ github.workspace }}/packages/eas-cli/dist/win32
- name: Upload x64 installer
uses: actions/upload-release-asset@v1
@@ -147,6 +147,14 @@ jobs:
run: yarn lerna publish from-package --yes --no-verify-access
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
- name: Add latest-eas-build-staging tag
run: |
VERSION=$(cat lerna.json | jq -r .version)
echo //registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN > ~/.npmrc
npm dist-tag add eas-cli@$VERSION latest-eas-build-staging
echo "Run \"npm dist-tag add eas-cli@$VERSION latest-eas-build\" to promote it to production."
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
release-changelog:
name: Update changelog and publish release
runs-on: ubuntu-latest
+104 -3
View File
@@ -8,6 +8,109 @@ This is the log of notable changes to EAS CLI and related packages.
### 🎉 New features
- Add `--json` flag to `eas config` command. ([#1568](https://github.com/expo/eas-cli/pull/1568) by [@wkozyra95](https://github.com/wkozyra95))
- Add M1 resource class configuration to default eas.json when running eas build:configure on a new project. ([#1637](https://github.com/expo/eas-cli/pull/1637) by [@brentvatne](https://github.com/brentvatne))
- Add prompt to switch iOS builds to M1 if the build queue is long. ([#1642](https://github.com/expo/eas-cli/pull/1642) by [@dsokal](https://github.com/dsokal))
### 🐛 Bug fixes
- Fix running commands with `--json` flag when EAS_NO_VCS is set. ([#1641](https://github.com/expo/eas-cli/pull/1641) by [@wkozyra95](https://github.com/wkozyra95))
### 🧹 Chores
- Remove unnecessary workaround for trailing backslash in .gitignore. ([#1622](https://github.com/expo/eas-cli/pull/1622) by [@wkozyra95](https://github.com/wkozyra95))
- Internal command that will be run on EAS worker when building from GitHub. ([#1568](https://github.com/expo/eas-cli/pull/1568) by [@wkozyra95](https://github.com/wkozyra95))
- Make the disabled tier error message more descriptive. ([#1635](https://github.com/expo/eas-cli/pull/1635) by [@dsokal](https://github.com/dsokal))
- Control some of the EAS Build error messages server-side. ([#1639](https://github.com/expo/eas-cli/pull/1639) by [@wkozyra95](https://github.com/wkozyra95))
## [3.3.2](https://github.com/expo/eas-cli/releases/tag/v3.3.2) - 2023-01-12
### 🐛 Bug fixes
- Add missing key information about updates in `eas update --json` and `eas update:view --json`. ([#1619](https://github.com/expo/eas-cli/pull/1619) by [@byCedric](https://github.com/byCedric))
### 🧹 Chores
- Upgrade dependencies. ([#1617](https://github.com/expo/eas-cli/pull/1617) by [@dsokal](https://github.com/dsokal))
- Improve handling `SSOUser` type. ([#1621](https://github.com/expo/eas-cli/pull/1621) by [@szdziedzic](https://github.com/szdziedzic))
## [3.3.1](https://github.com/expo/eas-cli/releases/tag/v3.3.1) - 2023-01-11
### 🐛 Bug fixes
- Revert missing key information about updates in `eas update --json` and `eas update:view --json`. ([d20db0f](https://github.com/expo/eas-cli/commit/d20db0fff42a6f4512fea426a66cb6f168e37f7c) by [@ide](https://github.com/ide))
## [3.3.0](https://github.com/expo/eas-cli/releases/tag/v3.3.0) - 2023-01-11
### 🎉 New features
- Add ability to select resource class for a build in build profile. ([#1609](https://github.com/expo/eas-cli/pull/1609) by [@dsokal](https://github.com/dsokal))
- Deprecate `--resource-class` flag. ([#1615](https://github.com/expo/eas-cli/pull/1615) by [@dsokal](https://github.com/dsokal))
- Add new resource classes and update already available. ([#1616](https://github.com/expo/eas-cli/pull/1616) by [@szdziedzic](https://github.com/szdziedzic))
### 🐛 Bug fixes
- Add missing key information about updates in `eas update --json` and `eas update:view --json`. ([#1611](https://github.com/expo/eas-cli/pull/1611) by [@byCedric](https://github.com/byCedric))
## [3.2.1](https://github.com/expo/eas-cli/releases/tag/v3.2.1) - 2023-01-09
### 🐛 Bug fixes
- Validate chosen build in the `eas build:run` command. ([#1614](https://github.com/expo/eas-cli/pull/1614) by [@szdziedzic](https://github.com/szdziedzic))
## [3.2.0](https://github.com/expo/eas-cli/releases/tag/v3.2.0) - 2023-01-09
### 🎉 New features
- Add `--channel` option to `update:republish`. ([#1580](https://github.com/expo/eas-cli/pull/1580) by [@byCedric](https://github.com/byCedric))
- Use `appVersion` as default runtime version policy when running `eas update:configure`. ([#1588](https://github.com/expo/eas-cli/pull/1588) by [@jonsamp](https://github.com/jonsamp))
- Support `--json` flag in webhook list command. ([#1605](https://github.com/expo/eas-cli/pull/1605) by [@sheddy7](https://github.com/sheddy7))
### 🐛 Bug fixes
- Makes eas.json configuration to only run on `update:configure`. ([#1598](https://github.com/expo/eas-cli/pull/1598) by [@jonsamp](https://github.com/jonsamp))
- Fix issue with invisible build info in some terminals in the `eas build:run` and `eas build:resign` commands. ([#1602](https://github.com/expo/eas-cli/pull/1602) by [@szdziedzic](https://github.com/szdziedzic))
- Fix issues with invisible build info in some terminals while using the `eas submit` command. ([#1603](https://github.com/expo/eas-cli/pull/1603) by [@szdziedzic](https://github.com/szdziedzic))
- Use the `completedAt` timestamp as the build finish date instead of the `updatedAt` timestamp in the `eas build:run` command. ([#1604](https://github.com/expo/eas-cli/pull/1604) by [@szdziedzic](https://github.com/szdziedzic))
### 🧹 Chores
- Make all URLs in logs clickable in terminals supporting hyperlinks. ([#1591](https://github.com/expo/eas-cli/pull/1591) by [@Simek](https://github.com/Simek))
- Use paginated select prompt for the `eas build:run` command. ([#1601](https://github.com/expo/eas-cli/pull/1601) by [@szdziedzic](https://github.com/szdziedzic))
## [3.1.1](https://github.com/expo/eas-cli/releases/tag/v3.1.1) - 2022-12-19
### 🐛 Bug fixes
- Fix update `--channel` and `--branch` flag validation. ([#1579](https://github.com/expo/eas-cli/pull/1579) by [@byCedric](https://github.com/byCedric))
## [3.1.0](https://github.com/expo/eas-cli/releases/tag/v3.1.0) - 2022-12-17
### 🎉 New features
- Adds `--channel` flag to `eas update`. ([#1567](https://github.com/expo/eas-cli/pull/1567) by [@jonsamp](https://github.com/jonsamp))
- Add channel configurations to **eas.json** during `eas update:configure`. ([#1570](https://github.com/expo/eas-cli/pull/1570) by [@jonsamp](https://github.com/jonsamp))
- Add `build:resign` command. ([#1575](https://github.com/expo/eas-cli/pull/1575) by [@wkozyra95](https://github.com/wkozyra95))
## [3.0.0](https://github.com/expo/eas-cli/releases/tag/v3.0.0) - 2022-12-07
### 🛠 Breaking changes
- Move update republish to separate command. ([#1533](https://github.com/expo/eas-cli/pull/1533) by [@byCedric](https://github.com/byCedric))
### 🐛 Bug fixes
- Make the not recognized image error handler run only if the image is present under a valid key and has an invalid value. ([#1565](https://github.com/expo/eas-cli/pull/1565) by [@szdziedzic](https://github.com/szdziedzic))
- Fix the `node:assert` import error by using imports from `assert` instead of from `node:assert`. ([#1569](https://github.com/expo/eas-cli/pull/1569) by [@szdziedzic](https://github.com/szdziedzic))
### 🧹 Chores
- Remove old republish code from the update command. ([#1535](https://github.com/expo/eas-cli/pull/1535) by [@byCedric](https://github.com/byCedric))
## [2.9.0](https://github.com/expo/eas-cli/releases/tag/v2.9.0) - 2022-12-05
### 🎉 New features
- Add caching for `eas build:run` command. ([#1542](https://github.com/expo/eas-cli/pull/1542) by [@szdziedzic](https://github.com/szdziedzic))
- Add `isGitWorkingTreeDirty` to EAS Update records. ([#1550](https://github.com/expo/eas-cli/pull/1550) by [@FiberJW](https://github.com/FiberJW))
- Prompt developer to download the app after the simulator build is finished. ([#1554](https://github.com/expo/eas-cli/pull/1554) by [@szdziedzic](https://github.com/szdziedzic))
@@ -18,8 +121,6 @@ This is the log of notable changes to EAS CLI and related packages.
- Disable selecting builds whose artifacts have expired in the `eas build:run` command. ([#1547](https://github.com/expo/eas-cli/pull/1547) by [@szdziedzic](https://github.com/szdziedzic))
- Change intent with which the `eas build:run` command opens an Android app to `android.intent.action.MAIN`. ([#1556](https://github.com/expo/eas-cli/pull/1556) by [@szdziedzic](https://github.com/szdziedzic))
### 🧹 Chores
## [2.8.0](https://github.com/expo/eas-cli/releases/tag/v2.8.0) - 2022-11-28
### 🎉 New features
@@ -317,7 +418,7 @@ This is the log of notable changes to EAS CLI and related packages.
- Add new option to `eas device:create` - allow importing devices from Apple Developer Portal. ([#1236](https://github.com/expo/eas-cli/pull/1236) by [@dsokal](https://github.com/dsokal))
- Add support for attaching messages to builds. ([#1237](https://github.com/expo/eas-cli/pull/1237) by [@dsokal](https://github.com/dsokal))
- Introduce interactive pagination for `branch` commands. ([#1213](https://github.com/expo/eas-cli/pull/1213) by [@kgc00](https://github.com/kgc00))
- Introduce interactive pagination for `branch` commands. ([#1213](https://github.com/expo/eas-cli/pull/1213) by [@kgc00](https://github.com/kgc00))
## [0.56.0](https://github.com/expo/eas-cli/releases/tag/v0.56.0) - 2022-07-28
+47 -3
View File
@@ -1,4 +1,48 @@
## Releasing a new version
# Development
1. Run `yarn release` in the repository root folder. The next version is chosen automatically based on the changelog entries. If you want to use different version, pass the version string as a positional argument to the command, e.g. `yarn release 1.2.3`.
2. That's it! GitHub Actions is going to take care of the rest. Watch the #eas-cli Slack channel for a successful release notification.
Set up an alias for the EAS CLI so you can try it in projects all around your computer. The project is compiled on the fly so you don't need to run a build (watch) command.
> The only exception is when you just cloned the repository or there have been changes in `packages/eas-json`. In that case, you'll have to run `yarn build` in the root.
Open your `.zshrc` or other config file and add:
```
alias easd="/PATH/TO/eas-cli/bin/run"
```
Then use it with `easd` like `easd build`.
If you're making changes to `packages/eas-json` or prefer/need to work with production code, start the build command in watch mode with:
```
yarn start
```
## Format
- Be sure to update the [`CHANGELOG.md`](./CHANGELOG.md) with changes for every PR. There is a changelog bot that can generate the proper entry for you. The instructions on how to use it are in the PR description placeholder.
- End `async` functions with `Async` like `runAsync`. This is just how we format functions at Expo.
- Utilize the unified `Log` module instead of `console.log`.
## Using local and staging API
For development against local API:
- Set up the API server as described at https://github.com/expo/universe/tree/main/server/www.
- Set the `EXPO_LOCAL=1` env variable either on every command run (e.g. `EXPO_LOCAL=1 easd ...`) or more permamently with `export EXPO_LOCAL=1` (works in a current shell session).
For development against staging API:
- Set the `EXPO_STAGING=1` env variable either on every command run (e.g. `EXPO_STAGING=1 easd ...`) or more permamently with `export EXPO_STAGING=1` (works in a current shell session).
## Working on local builds (`eas build --local`)
See https://github.com/expo/eas-build/blob/main/DEVELOPMENT.md for how to set up your environment when making changes to [`eas-cli-local-build-plugin`](https://github.com/expo/eas-build/tree/main/packages/local-build-plugin) and/or [`build-tools`](https://github.com/expo/eas-build/tree/main/packages/build-tools).
## Testing
Run `yarn test` either in the repository root or in a package directory that you're working on.
## Releasing
See [RELEASING.md](./RELEASING.md).
+18
View File
@@ -0,0 +1,18 @@
# Releasing EAS CLI
1. Run `yarn release` in the repository root folder. The next version is chosen automatically based on the changelog entries. If you want to use different version, pass the version string as a positional argument to the command, e.g. `yarn release 1.2.3`.
2. That's it! GitHub Actions is going to take care of the rest. Watch the #eas-cli Slack channel for a successful release notification.
## Choosing the next version
As stated above, the next EAS CLI version is chosen automatically based on the existing changelog entries under the unreleased section in **CHANGELOG.md**.
The algorithm works as follows:
- If there are any entries in the "🛠 Breaking changes" section, bump the MAJOR version.
- Otherwise, if there are any entries in the "🎉 New features", bump the MINOR version.
- Otherwise, bump the PATCH version.
## Updating EAS CLI version on EAS Build
The release process promotes the new version to staging. After verifying it works there, you can promote it to production with `npm dist-tag add eas-cli@{version} latest-eas-build`.
+2 -1
View File
@@ -1,5 +1,6 @@
{
"npmClient": "yarn",
"useWorkspaces": true,
"version": "2.9.0"
"version": "3.4.0",
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
}
+12 -11
View File
@@ -1,4 +1,5 @@
{
"name": "eas-cli-root",
"private": true,
"workspaces": [
"packages/*"
@@ -18,19 +19,19 @@
"clean": "lerna run clean && rm -rf node_modules coverage"
},
"devDependencies": {
"@types/jest": "29.2.0",
"@types/node": "18.11.5",
"eslint": "8.26.0",
"eslint-config-universe": "11.1.0",
"eslint-plugin-async-protect": "2.1.0",
"@types/jest": "29.2.5",
"@types/node": "18.11.18",
"eslint": "8.31.0",
"eslint-config-universe": "11.1.1",
"eslint-plugin-async-protect": "3.0.0",
"eslint-plugin-node": "11.1.0",
"jest": "29.2.2",
"jest-watch-typeahead": "2.2.0",
"lerna": "6.0.1",
"oclif": "3.2.22",
"prettier": "2.7.1",
"jest": "29.3.1",
"jest-watch-typeahead": "2.2.1",
"lerna": "6.4.1",
"oclif": "3.4.3",
"prettier": "2.8.2",
"ts-jest": "29.0.3",
"typescript": "4.8.4"
"typescript": "4.9.4"
},
"volta": {
"node": "18.6.0",
+115 -108
View File
@@ -70,6 +70,7 @@ eas --help COMMAND
* [`eas build:configure`](#eas-buildconfigure)
* [`eas build:inspect`](#eas-buildinspect)
* [`eas build:list`](#eas-buildlist)
* [`eas build:resign`](#eas-buildresign)
* [`eas build:run`](#eas-buildrun)
* [`eas build:submit`](#eas-buildsubmit)
* [`eas build:version:set`](#eas-buildversionset)
@@ -96,8 +97,6 @@ eas --help COMMAND
* [`eas open`](#eas-open)
* [`eas project:info`](#eas-projectinfo)
* [`eas project:init`](#eas-projectinit)
* [`eas run`](#eas-run)
* [`eas run:run`](#eas-runrun)
* [`eas secret:create`](#eas-secretcreate)
* [`eas secret:delete`](#eas-secretdelete)
* [`eas secret:list`](#eas-secretlist)
@@ -107,6 +106,7 @@ eas --help COMMAND
* [`eas update:configure`](#eas-updateconfigure)
* [`eas update:delete GROUPID`](#eas-updatedelete-groupid)
* [`eas update:list`](#eas-updatelist)
* [`eas update:republish`](#eas-updaterepublish)
* [`eas update:view GROUPID`](#eas-updateview-groupid)
* [`eas webhook:create`](#eas-webhookcreate)
* [`eas webhook:delete [ID]`](#eas-webhookdelete-id)
@@ -130,7 +130,7 @@ ALIASES
$ eas login
```
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/account/login.ts)_
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/account/login.ts)_
## `eas account:logout`
@@ -147,7 +147,7 @@ ALIASES
$ eas logout
```
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/account/logout.ts)_
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/account/logout.ts)_
## `eas account:view`
@@ -164,7 +164,7 @@ ALIASES
$ eas whoami
```
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/account/view.ts)_
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/account/view.ts)_
## `eas analytics [STATUS]`
@@ -178,7 +178,7 @@ DESCRIPTION
display or change analytics settings
```
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/analytics.ts)_
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/analytics.ts)_
## `eas autocomplete [SHELL]`
@@ -207,7 +207,7 @@ EXAMPLES
$ eas autocomplete --refresh-cache
```
_See code: [@oclif/plugin-autocomplete](https://github.com/oclif/plugin-autocomplete/blob/v1.3.4/src/commands/autocomplete/index.ts)_
_See code: [@oclif/plugin-autocomplete](https://github.com/oclif/plugin-autocomplete/blob/v1.3.10/src/commands/autocomplete/index.ts)_
## `eas branch:create [NAME]`
@@ -228,7 +228,7 @@ DESCRIPTION
create a branch
```
_See code: [src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/branch/create.ts)_
_See code: [src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/branch/create.ts)_
## `eas branch:delete [NAME]`
@@ -249,7 +249,7 @@ DESCRIPTION
delete a branch
```
_See code: [src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/branch/delete.ts)_
_See code: [src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/branch/delete.ts)_
## `eas branch:list`
@@ -269,7 +269,7 @@ DESCRIPTION
list all branches
```
_See code: [src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/branch/list.ts)_
_See code: [src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/branch/list.ts)_
## `eas branch:rename`
@@ -289,7 +289,7 @@ DESCRIPTION
rename a branch
```
_See code: [src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/branch/rename.ts)_
_See code: [src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/branch/rename.ts)_
## `eas branch:view [NAME]`
@@ -312,7 +312,7 @@ DESCRIPTION
view a branch
```
_See code: [src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/branch/view.ts)_
_See code: [src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/branch/view.ts)_
## `eas build`
@@ -342,7 +342,7 @@ DESCRIPTION
start a build
```
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/build/index.ts)_
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/build/index.ts)_
## `eas build:cancel [BUILD_ID]`
@@ -359,7 +359,7 @@ DESCRIPTION
cancel a build
```
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/build/cancel.ts)_
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/build/cancel.ts)_
## `eas build:configure`
@@ -376,7 +376,7 @@ DESCRIPTION
configure the project to support EAS Build
```
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/build/configure.ts)_
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/build/configure.ts)_
## `eas build:inspect`
@@ -411,7 +411,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/v2.9.0/packages/eas-cli/src/commands/build/inspect.ts)_
_See code: [src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/build/inspect.ts)_
## `eas build:list`
@@ -448,7 +448,33 @@ DESCRIPTION
list all builds for your project
```
_See code: [src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/build/list.ts)_
_See code: [src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/build/list.ts)_
## `eas build:resign`
re-sign a build archive
```
USAGE
$ eas build:resign [-p android|ios] [-e <value>] [--wait] [--id <value>] [--offset <value>] [--limit <value>]
[--json --non-interactive]
FLAGS
-e, --profile=PROFILE_NAME Name of the build profile from eas.json. Defaults to "production" if defined in
eas.json.
-p, --platform=(android|ios)
--id=<value> ID of the build to re-sign.
--json Enable JSON output, non-JSON messages will be printed to stderr.
--limit=<value> The number of items to fetch each query. Defaults to 50 and is capped at 100.
--non-interactive Run the command in non-interactive mode.
--offset=<value> Start queries from specified index. Use for paginating results. Defaults to 0.
--[no-]wait Wait for build(s) to complete.
DESCRIPTION
re-sign a build archive
```
_See code: [src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/build/resign.ts)_
## `eas build:run`
@@ -472,7 +498,7 @@ DESCRIPTION
run simulator/emulator builds from eas-cli
```
_See code: [src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/build/run.ts)_
_See code: [src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/build/run.ts)_
## `eas build:submit`
@@ -519,7 +545,7 @@ DESCRIPTION
Update version of an app.
```
_See code: [src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v2.9.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/v3.4.0/packages/eas-cli/src/commands/build/version/set.ts)_
## `eas build:version:sync`
@@ -538,7 +564,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/v2.9.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/v3.4.0/packages/eas-cli/src/commands/build/version/sync.ts)_
## `eas build:view [BUILD_ID]`
@@ -555,7 +581,7 @@ DESCRIPTION
view a build for your project
```
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/build/view.ts)_
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/build/view.ts)_
## `eas channel:create [NAME]`
@@ -576,7 +602,7 @@ DESCRIPTION
create a channel
```
_See code: [src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/channel/create.ts)_
_See code: [src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/channel/create.ts)_
## `eas channel:edit [NAME]`
@@ -598,7 +624,7 @@ DESCRIPTION
point a channel at a new branch
```
_See code: [src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/channel/edit.ts)_
_See code: [src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/channel/edit.ts)_
## `eas channel:list`
@@ -618,7 +644,7 @@ DESCRIPTION
list all channels
```
_See code: [src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/channel/list.ts)_
_See code: [src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/channel/list.ts)_
## `eas channel:view [NAME]`
@@ -641,7 +667,7 @@ DESCRIPTION
view a channel
```
_See code: [src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/channel/view.ts)_
_See code: [src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/channel/view.ts)_
## `eas config`
@@ -649,18 +675,20 @@ display project configuration (app.json + eas.json)
```
USAGE
$ eas config [-p android|ios] [-e <value>]
$ eas config [-p android|ios] [-e <value>] [--json --non-interactive]
FLAGS
-e, --profile=PROFILE_NAME Name of the build profile from eas.json. Defaults to "production" if defined in
eas.json.
-p, --platform=(android|ios)
--json Enable JSON output, non-JSON messages will be printed to stderr.
--non-interactive Run the command in non-interactive mode.
DESCRIPTION
display project configuration (app.json + eas.json)
```
_See code: [src/commands/config.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/config.ts)_
_See code: [src/commands/config.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/config.ts)_
## `eas credentials`
@@ -677,7 +705,7 @@ DESCRIPTION
manage credentials
```
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/credentials.ts)_
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/credentials.ts)_
## `eas device:create`
@@ -691,7 +719,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/v2.9.0/packages/eas-cli/src/commands/device/create.ts)_
_See code: [src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/device/create.ts)_
## `eas device:delete`
@@ -711,7 +739,7 @@ DESCRIPTION
remove a registered device from your account
```
_See code: [src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/device/delete.ts)_
_See code: [src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/device/delete.ts)_
## `eas device:list`
@@ -732,7 +760,7 @@ DESCRIPTION
list all registered devices for your account
```
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/device/list.ts)_
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/device/list.ts)_
## `eas device:view [UDID]`
@@ -746,7 +774,7 @@ DESCRIPTION
view a device for your project
```
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/device/view.ts)_
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/device/view.ts)_
## `eas diagnostics`
@@ -760,7 +788,7 @@ DESCRIPTION
display environment info
```
_See code: [src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/diagnostics.ts)_
_See code: [src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/diagnostics.ts)_
## `eas help [COMMAND]`
@@ -780,7 +808,7 @@ DESCRIPTION
display help for eas-cli
```
_See code: [@expo/plugin-help](https://github.com/expo/oclif-plugin-help/blob/v5.1.16/src/commands/help.ts)_
_See code: [@expo/plugin-help](https://github.com/expo/oclif-plugin-help/blob/v5.1.22/src/commands/help.ts)_
## `eas init`
@@ -848,7 +876,7 @@ DESCRIPTION
validate the local store configuration
```
_See code: [src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/metadata/lint.ts)_
_See code: [src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/metadata/lint.ts)_
## `eas metadata:pull`
@@ -865,7 +893,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/v2.9.0/packages/eas-cli/src/commands/metadata/pull.ts)_
_See code: [src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/metadata/pull.ts)_
## `eas metadata:push`
@@ -882,7 +910,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/v2.9.0/packages/eas-cli/src/commands/metadata/push.ts)_
_See code: [src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/metadata/push.ts)_
## `eas open`
@@ -896,7 +924,7 @@ DESCRIPTION
open the project page in a web browser
```
_See code: [src/commands/open.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/open.ts)_
_See code: [src/commands/open.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/open.ts)_
## `eas project:info`
@@ -910,7 +938,7 @@ DESCRIPTION
information about the current project
```
_See code: [src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/project/info.ts)_
_See code: [src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/project/info.ts)_
## `eas project:init`
@@ -932,55 +960,7 @@ ALIASES
$ eas init
```
_See code: [src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/project/init.ts)_
## `eas run`
run simulator build
```
USAGE
$ eas run [--latest | --id <value> | --path <value> | --url <value>] [-p android|ios|all] [--offset
<value>] [--limit <value>]
FLAGS
-p, --platform=(android|ios|all)
--id=<value> ID of the simulator build to run
--latest Run the latest simulator build for specified platform
--limit=<value> The number of items to fetch each query. Defaults to 50 and is capped at 100.
--offset=<value> Start queries from specified index. Use for paginating results. Defaults to 0.
--path=<value> Path to the simulator build file file
--url=<value> Simulator build archive url
DESCRIPTION
run simulator build
```
_See code: [src/commands/run/index.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/run/index.ts)_
## `eas run:run`
run simulator build
```
USAGE
$ eas run:run [--latest | --id <value> | --path <value> | --url <value>] [-p android|ios|all] [--offset
<value>] [--limit <value>]
FLAGS
-p, --platform=(android|ios|all)
--id=<value> ID of the simulator build to run
--latest Run the latest simulator build for specified platform
--limit=<value> The number of items to fetch each query. Defaults to 50 and is capped at 100.
--offset=<value> Start queries from specified index. Use for paginating results. Defaults to 0.
--path=<value> Path to the simulator build file file
--url=<value> Simulator build archive url
DESCRIPTION
run simulator build
```
_See code: [src/commands/run/run.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/run/run.ts)_
_See code: [src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/project/init.ts)_
## `eas secret:create`
@@ -1003,7 +983,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/v2.9.0/packages/eas-cli/src/commands/secret/create.ts)_
_See code: [src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/secret/create.ts)_
## `eas secret:delete`
@@ -1021,7 +1001,7 @@ DESCRIPTION
delete an environment secret by ID
```
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/secret/delete.ts)_
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/secret/delete.ts)_
## `eas secret:list`
@@ -1035,7 +1015,7 @@ DESCRIPTION
list environment secrets available for your current app
```
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/secret/list.ts)_
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/secret/list.ts)_
## `eas secret:push`
@@ -1055,7 +1035,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/v2.9.0/packages/eas-cli/src/commands/secret/push.ts)_
_See code: [src/commands/secret/push.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/secret/push.ts)_
## `eas submit`
@@ -1085,7 +1065,7 @@ ALIASES
$ eas build:submit
```
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/submit.ts)_
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/submit.ts)_
## `eas update`
@@ -1093,14 +1073,16 @@ publish an update group
```
USAGE
$ eas update [--branch <value>] [--message <value>] [--republish | --input-dir <value> | --skip-bundler]
[--group <value> | | ] [-p android|ios|all] [--auto] [--private-key-path <value>] [--json --non-interactive]
$ eas update [--branch <value>] [--channel <value>] [--message <value>] [--republish | --input-dir <value>
| --skip-bundler] [--group <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 update group on
--group=<value> Update group to republish
--channel=<value> Channel that the published update should affect
--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.
--message=<value> A short message describing the update
@@ -1108,14 +1090,14 @@ 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.
--republish Republish an update group
--republish Republish an update group (deprecated, see republish command)
--skip-bundler Skip running Expo CLI to bundle the app before publishing
DESCRIPTION
publish an update group
```
_See code: [src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/update/index.ts)_
_See code: [src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/update/index.ts)_
## `eas update:configure`
@@ -1133,7 +1115,7 @@ DESCRIPTION
configure the project to support EAS Update
```
_See code: [src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/update/configure.ts)_
_See code: [src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/update/configure.ts)_
## `eas update:delete GROUPID`
@@ -1154,7 +1136,7 @@ DESCRIPTION
delete all the updates in an update group
```
_See code: [src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/update/delete.ts)_
_See code: [src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/update/delete.ts)_
## `eas update:list`
@@ -1176,7 +1158,31 @@ DESCRIPTION
view the recent updates
```
_See code: [src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/update/list.ts)_
_See code: [src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/update/list.ts)_
## `eas update:republish`
rollback to an existing update
```
USAGE
$ eas update:republish [--channel <value> | --branch <value> | --group <value>] [--message <value>] [-p
android|ios|all] [--json --non-interactive]
FLAGS
-p, --platform=(android|ios|all) [default: all]
--branch=<value> Branch name to select an update to republish from
--channel=<value> Channel name to select an update to republish from
--group=<value> Update group ID to republish
--json Enable JSON output, non-JSON messages will be printed to stderr.
--message=<value> Short message describing the republished update
--non-interactive Run the command in non-interactive mode.
DESCRIPTION
rollback to an existing update
```
_See code: [src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/update/republish.ts)_
## `eas update:view GROUPID`
@@ -1196,7 +1202,7 @@ DESCRIPTION
update group details
```
_See code: [src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/update/view.ts)_
_See code: [src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/update/view.ts)_
## `eas webhook:create`
@@ -1217,7 +1223,7 @@ DESCRIPTION
create a webhook
```
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/webhook/create.ts)_
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/webhook/create.ts)_
## `eas webhook:delete [ID]`
@@ -1237,7 +1243,7 @@ DESCRIPTION
delete a webhook
```
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/webhook/delete.ts)_
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/webhook/delete.ts)_
## `eas webhook:list`
@@ -1245,16 +1251,17 @@ list webhooks
```
USAGE
$ eas webhook:list [--event BUILD|SUBMIT]
$ eas webhook:list [--event BUILD|SUBMIT] [--json]
FLAGS
--event=(BUILD|SUBMIT) Event type that triggers the webhook
--json Enable JSON output, non-JSON messages will be printed to stderr.
DESCRIPTION
list webhooks
```
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/webhook/list.ts)_
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/webhook/list.ts)_
## `eas webhook:update`
@@ -1276,7 +1283,7 @@ DESCRIPTION
update a webhook
```
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/webhook/update.ts)_
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/webhook/update.ts)_
## `eas webhook:view ID`
@@ -1293,7 +1300,7 @@ DESCRIPTION
view a webhook
```
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v2.9.0/packages/eas-cli/src/commands/webhook/view.ts)_
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v3.4.0/packages/eas-cli/src/commands/webhook/view.ts)_
## `eas whoami`
+4073 -2073
View File
File diff suppressed because it is too large. Load diff
+33 -33
View File
@@ -1,7 +1,7 @@
{
"name": "eas-cli",
"description": "EAS command line tool",
"version": "2.9.0",
"version": "3.4.0",
"author": "Expo <[email protected]>",
"bin": {
"eas": "./bin/run"
@@ -9,31 +9,31 @@
"bugs": "https://github.com/expo/eas-cli/issues",
"dependencies": {
"@expo/apple-utils": "0.0.0-alpha.34",
"@expo/code-signing-certificates": "0.0.3",
"@expo/config": "7.0.1",
"@expo/config-plugins": "5.0.1",
"@expo/config-types": "46.0.2",
"@expo/eas-build-job": "0.2.97",
"@expo/eas-json": "2.8.0",
"@expo/json-file": "8.2.36",
"@expo/code-signing-certificates": "0.0.5",
"@expo/config": "7.0.3",
"@expo/config-plugins": "5.0.4",
"@expo/config-types": "47.0.0",
"@expo/eas-build-job": "0.2.102",
"@expo/eas-json": "3.3.2",
"@expo/json-file": "8.2.37",
"@expo/multipart-body-parser": "1.1.0",
"@expo/osascript": "2.0.33",
"@expo/package-manager": "0.0.56",
"@expo/package-manager": "0.0.57",
"@expo/pkcs12": "0.0.8",
"@expo/plist": "0.0.18",
"@expo/plugin-help": "5.1.16",
"@expo/plugin-warn-if-update-available": "2.4.0",
"@expo/prebuild-config": "5.0.3",
"@expo/plist": "0.0.20",
"@expo/plugin-help": "5.1.22",
"@expo/plugin-warn-if-update-available": "2.5.0",
"@expo/prebuild-config": "5.0.7",
"@expo/results": "1.0.0",
"@expo/rudder-sdk-node": "1.1.1",
"@expo/spawn-async": "1.7.0",
"@expo/timeago.js": "1.0.0",
"@oclif/core": "1.19.2",
"@oclif/plugin-autocomplete": "1.3.4",
"@oclif/core": "1.23.2",
"@oclif/plugin-autocomplete": "1.3.10",
"@segment/ajv-human-errors": "^2.1.2",
"@urql/core": "3.0.5",
"@urql/core": "3.1.1",
"@urql/exchange-retry": "1.0.0",
"ajv": "^8.11.0",
"ajv": "8.11.0",
"ajv-formats": "2.1.1",
"better-opn": "3.0.2",
"chalk": "4.1.2",
@@ -52,14 +52,14 @@
"graphql": "16.6.0",
"graphql-tag": "2.12.6",
"https-proxy-agent": "5.0.1",
"ignore": "5.2.0",
"ignore": "5.2.4",
"indent-string": "4.0.0",
"jks-js": "1.1.0",
"joi": "17.6.4",
"joi": "17.7.0",
"keychain": "1.3.0",
"log-symbols": "4.1.0",
"mime": "3.0.0",
"minimatch": "5.1.0",
"minimatch": "5.1.2",
"nanoid": "3.3.4",
"node-fetch": "2.6.7",
"node-forge": "1.3.1",
@@ -74,47 +74,47 @@
"resolve-from": "5.0.0",
"semver": "7.3.8",
"slash": "3.0.0",
"tar": "6.1.11",
"tar": "6.1.13",
"terminal-link": "2.1.1",
"tslib": "2.4.0",
"tslib": "2.4.1",
"turndown": "7.1.1",
"untildify": "4.0.0",
"uuid": "9.0.0",
"wrap-ansi": "7.0.0"
},
"devDependencies": {
"@graphql-codegen/cli": "2.13.7",
"@graphql-codegen/introspection": "2.2.1",
"@graphql-codegen/typescript": "2.8.0",
"@graphql-codegen/typescript-operations": "2.5.5",
"@graphql-codegen/cli": "2.16.3",
"@graphql-codegen/introspection": "2.2.3",
"@graphql-codegen/typescript": "2.8.7",
"@graphql-codegen/typescript-operations": "2.5.12",
"@types/cli-progress": "3.11.0",
"@types/dateformat": "3.0.1",
"@types/envinfo": "7.8.1",
"@types/express": "4.17.14",
"@types/express": "4.17.15",
"@types/fs-extra": "9.0.13",
"@types/getenv": "^1.0.0",
"@types/mime": "3.0.1",
"@types/node-fetch": "2.6.2",
"@types/node-forge": "1.3.0",
"@types/node-forge": "1.3.1",
"@types/pngjs": "6.0.1",
"@types/promise-retry": "1.1.3",
"@types/prompts": "2.4.1",
"@types/semver": "7.3.12",
"@types/prompts": "2.4.2",
"@types/semver": "7.3.13",
"@types/tar": "6.1.3",
"@types/tough-cookie": "4.0.2",
"@types/uuid": "8.3.4",
"@types/uuid": "9.0.0",
"@types/wrap-ansi": "3.0.0",
"axios": "0.27.2",
"eslint-plugin-graphql": "4.0.0",
"express": "4.18.2",
"memfs": "3.4.7",
"memfs": "3.4.13",
"mockdate": "3.0.5",
"nock": "13.2.9",
"rimraf": "3.0.2",
"ts-deepmerge": "4.0.0",
"ts-mockito": "2.6.1",
"ts-node": "10.9.1",
"typescript": "4.8.4"
"typescript": "4.9.4"
},
"engines": {
"node": ">=14.0.0"
+3 -2
View File
@@ -15,6 +15,7 @@ import Log from '../log';
import { formatBranch, getBranchDescription } from '../update/utils';
import { printJsonOnlyOutput } from '../utils/json';
import {
SelectPromptEntry,
paginatedQueryWithConfirmPromptAsync,
paginatedQueryWithSelectPromptAsync,
} from '../utils/queries';
@@ -31,7 +32,7 @@ export async function selectBranchOnAppAsync(
paginatedQueryOptions,
}: {
projectId: string;
displayTextForListItem: (queryItem: UpdateBranchFragment) => string;
displayTextForListItem: (queryItem: UpdateBranchFragment) => SelectPromptEntry;
promptTitle: string;
paginatedQueryOptions: PaginatedQueryOptions;
}
@@ -48,7 +49,7 @@ export async function selectBranchOnAppAsync(
promptOptions: {
title: promptTitle,
getIdentifierForQueryItem: updateBranchFragment => updateBranchFragment.id,
createDisplayTextForSelectionPromptListItem: displayTextForListItem,
makePartialChoiceObject: displayTextForListItem,
},
});
if (!selectedBranch) {
@@ -3,7 +3,13 @@ import { v4 as uuid } from 'uuid';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { selectBuildToCancelAsync } from '../../commands/build/cancel';
import { AppPlatform, BuildFragment, BuildPriority, BuildStatus } from '../../graphql/generated';
import {
AppPlatform,
BuildFragment,
BuildPriority,
BuildResourceClass,
BuildStatus,
} from '../../graphql/generated';
import { BuildQuery } from '../../graphql/queries/BuildQuery';
import { confirmAsync, selectAsync } from '../../prompts';
@@ -85,5 +91,6 @@ function createMockBuildFragment({
},
},
status: BuildStatus.InQueue,
resourceClass: BuildResourceClass.AndroidMedium,
};
}
@@ -1,4 +1,12 @@
import { Android, ArchiveSource, Job, Platform, sanitizeJob } from '@expo/eas-build-job';
import {
Android,
ArchiveSource,
BuildMode,
BuildTrigger,
Job,
Platform,
sanitizeJob,
} from '@expo/eas-build-job';
import { BuildProfile } from '@expo/eas-json';
import path from 'path';
import slash from 'slash';
@@ -83,6 +91,8 @@ export async function prepareJobAsync(
experimental: {
prebuildCommand: ctx.buildProfile.prebuildCommand,
},
mode: BuildMode.BUILD,
triggeredBy: BuildTrigger.EAS_CLI,
};
return sanitizeJob(job);
+136 -48
View File
@@ -1,5 +1,6 @@
import { ArchiveSource, ArchiveSourceType, Job, Metadata, Platform } from '@expo/eas-build-job';
import { CredentialsSource } from '@expo/eas-json';
import { CredentialsSource, EasJsonAccessor, EasJsonUtils, ResourceClass } from '@expo/eas-json';
import assert from 'assert';
import chalk from 'chalk';
import cliProgress from 'cli-progress';
import fs from 'fs-extra';
@@ -14,6 +15,7 @@ import {
BuildFragment,
BuildParamsInput,
BuildPriority,
BuildResourceClass,
BuildStatus,
UploadSessionType,
} from '../graphql/generated';
@@ -26,13 +28,15 @@ 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 { runLocalBuildAsync } from './local';
import { LocalBuildMode, runLocalBuildAsync } from './local';
import { collectMetadataAsync } from './metadata';
import { printDeprecationWarnings } from './utils/printBuildInfo';
import { makeProjectTarballAsync, reviewAndCommitChangesAsync } from './utils/repository';
@@ -107,15 +111,24 @@ export async function prepareBuildRequestForPlatformAsync<
);
}
const projectArchive = ctx.localBuildOptions.enable
? ({
type: ArchiveSourceType.PATH,
path: (await makeProjectTarballAsync()).path,
} as const)
: ({
type: ArchiveSourceType.GCS,
bucketKey: await uploadProjectAsync(ctx),
} as const);
let projectArchive: ArchiveSource | undefined;
if (ctx.localBuildOptions.localBuildMode === LocalBuildMode.LOCAL_BUILD_PLUGIN) {
projectArchive = {
type: ArchiveSourceType.PATH,
path: (await makeProjectTarballAsync()).path,
};
} else if (ctx.localBuildOptions.localBuildMode === LocalBuildMode.INTERNAL) {
projectArchive = {
type: ArchiveSourceType.PATH,
path: process.cwd(),
};
} else if (!ctx.localBuildOptions.localBuildMode) {
projectArchive = {
type: ArchiveSourceType.GCS,
bucketKey: await uploadProjectAsync(ctx),
};
}
assert(projectArchive);
const metadata = await collectMetadataAsync(ctx);
const buildParams = resolveBuildParamsInput(ctx);
@@ -125,22 +138,36 @@ export async function prepareBuildRequestForPlatformAsync<
});
return async () => {
if (ctx.localBuildOptions.enable) {
if (ctx.localBuildOptions.localBuildMode === LocalBuildMode.LOCAL_BUILD_PLUGIN) {
await runLocalBuildAsync(job, metadata, ctx.localBuildOptions);
return undefined;
} else {
} else if (ctx.localBuildOptions.localBuildMode === LocalBuildMode.INTERNAL) {
printJsonOnlyOutput({ job, metadata });
return undefined;
} else if (!ctx.localBuildOptions.localBuildMode) {
try {
return await sendBuildRequestAsync(builder, job, metadata, buildParams);
} catch (error: any) {
handleBuildRequestError(error, job.platform);
}
} else {
throw new Error('Unknown localBuildMode.');
}
};
}
const SERVER_SIDE_DEFINED_ERRORS = [
'TURTLE_DEPRECATED_JOB_FORMAT',
'EAS_BUILD_FREE_TIER_DISABLED',
'EAS_BUILD_FREE_TIER_DISABLED_IOS',
'EAS_BUILD_FREE_TIER_DISABLED_ANDROID',
];
function handleBuildRequestError(error: any, platform: Platform): never {
if (error?.graphQLErrors?.[0]?.extensions?.errorCode === 'TURTLE_DEPRECATED_JOB_FORMAT') {
Log.error('EAS Build API has changed. Upgrade to the latest eas-cli version.');
Log.debug(JSON.stringify(error.graphQLErrors, null, 2));
if (SERVER_SIDE_DEFINED_ERRORS.includes(error?.graphQLErrors?.[0]?.extensions?.errorCode)) {
Log.error(error?.graphQLErrors?.[0]?.message);
throw new Error('Build request failed.');
} else if (
error?.graphQLErrors?.[0]?.extensions?.errorCode === 'EAS_BUILD_DOWN_FOR_MAINTENANCE'
@@ -151,31 +178,6 @@ function handleBuildRequestError(error: any, platform: Platform): never {
)} for updates.`
);
throw new Error('Build request failed.');
} else if (error?.graphQLErrors?.[0]?.extensions?.errorCode === 'EAS_BUILD_FREE_TIER_DISABLED') {
Log.error(
`EAS Build free tier is temporarily disabled and we are not accepting any new builds. Try again later. ${learnMore(
'https://expo.fyi/eas-build-queues'
)}`
);
throw new Error('Build request failed.');
} else if (
error?.graphQLErrors?.[0]?.extensions?.errorCode === 'EAS_BUILD_FREE_TIER_DISABLED_IOS'
) {
Log.error(
`EAS Build free tier is temporarily disabled for iOS and we are not accepting any new builds. Try again later. ${learnMore(
'https://expo.fyi/eas-build-queues'
)}`
);
throw new Error('Build request failed.');
} else if (
error?.graphQLErrors?.[0]?.extensions?.errorCode === 'EAS_BUILD_FREE_TIER_DISABLED_ANDROID'
) {
Log.error(
`EAS Build free tier is temporarily disabled for Android and we are not accepting any new builds. Try again later. ${learnMore(
'https://expo.fyi/eas-build-queues'
)}`
);
throw new Error('Build request failed.');
} else if (
error?.graphQLErrors?.[0]?.extensions?.errorCode === 'EAS_BUILD_TOO_MANY_PENDING_BUILDS'
) {
@@ -285,7 +287,12 @@ export type MaybeBuildFragment = BuildFragment | null;
export async function waitForBuildEndAsync(
graphqlClient: ExpoGraphqlClient,
{ buildIds, accountName }: { buildIds: string[]; accountName: string },
{
buildIds,
accountName,
projectDir,
nonInteractive,
}: { buildIds: string[]; accountName: string; projectDir: string; nonInteractive: boolean },
{ intervalSec = 10 } = {}
): Promise<MaybeBuildFragment[]> {
let spinner;
@@ -302,7 +309,10 @@ export async function waitForBuildEndAsync(
const builds = await getBuildsSafelyAsync(graphqlClient, buildIds);
const { refetch } =
builds.length === 1
? await handleSingleBuildProgressAsync({ build: builds[0], accountName }, { spinner })
? await handleSingleBuildProgressAsync(
{ build: builds[0], accountName, projectDir, nonInteractive },
{ spinner }
)
: await handleMultipleBuildsProgressAsync({ builds }, { spinner, originalSpinnerText });
if (!refetch) {
return builds;
@@ -337,7 +347,17 @@ const queueProgressBar = new cliProgress.SingleBar(
);
async function handleSingleBuildProgressAsync(
{ build, accountName }: { build: MaybeBuildFragment; accountName: string },
{
build,
accountName,
projectDir,
nonInteractive,
}: {
build: MaybeBuildFragment;
accountName: string;
projectDir: string;
nonInteractive: boolean;
},
{ spinner }: { spinner: Ora }
): Promise<BuildProgressResult> {
if (build === null) {
@@ -362,7 +382,7 @@ async function handleSingleBuildProgressAsync(
spinner.succeed('Build finished');
return { refetch: false };
case BuildStatus.New:
spinner.text = `Build is waiting to enter the queue. Check your concurrency limit at ${chalk.underline(
spinner.text = `Build is waiting to enter the queue. Check your concurrency limit at ${link(
formatAccountSubscriptionsUrl(accountName)
)}.`;
break;
@@ -376,18 +396,68 @@ async function handleSingleBuildProgressAsync(
if (
!queueProgressBarStarted &&
typeof build.initialQueuePosition === 'number' &&
typeof build.queuePosition === 'number'
typeof build.queuePosition === 'number' &&
typeof build.estimatedWaitTimeLeftSeconds === 'number'
) {
spinner.stopAndPersist();
if (build.priority !== BuildPriority.High) {
Log.newLine();
Log.log('Start builds sooner in the priority queue.');
Log.log(
`Sign up for EAS Production or Enterprise at ${chalk.underline(
`Sign up for EAS Production or Enterprise at ${link(
formatAccountSubscriptionsUrl(accountName)
)}`
);
}
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(
@@ -423,8 +493,8 @@ async function handleSingleBuildProgressAsync(
}
const priorityToQueueDisplayName: Record<BuildPriority, string> = {
[BuildPriority.Normal]: 'queue',
[BuildPriority.NormalPlus]: 'queue',
[BuildPriority.Normal]: 'Free tier queue',
[BuildPriority.NormalPlus]: 'Free tier queue',
[BuildPriority.High]: 'priority queue',
};
@@ -529,3 +599,21 @@ function formatAccountSubscriptionsUrl(accountName: string): string {
getExpoWebsiteBaseUrl()
).toString();
}
async function updateIosBuildProfilesToUseM1WorkersAsync(projectDir: string): Promise<void> {
const easJsonAccessor = new EasJsonAccessor(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.M1_MEDIUM,
};
}
return easJsonRawObject;
});
await easJsonAccessor.writeAsync();
Log.withTick('Updated eas.json. Your next builds will run on M1 workers.');
}
+21 -3
View File
@@ -1,5 +1,5 @@
import { Platform, Workflow } from '@expo/eas-build-job';
import { EasJson, EasJsonAccessor } from '@expo/eas-json';
import { EasJson, EasJsonAccessor, ResourceClass } from '@expo/eas-json';
import chalk from 'chalk';
import fs from 'fs-extra';
@@ -53,11 +53,21 @@ const EAS_JSON_MANAGED_DEFAULT: EasJson = {
development: {
developmentClient: true,
distribution: 'internal',
ios: {
resourceClass: ResourceClass.M1_MEDIUM,
},
},
preview: {
distribution: 'internal',
ios: {
resourceClass: ResourceClass.M1_MEDIUM,
},
},
production: {
ios: {
resourceClass: ResourceClass.M1_MEDIUM,
},
},
production: {},
},
submit: {
production: {},
@@ -76,12 +86,20 @@ const EAS_JSON_BARE_DEFAULT: EasJson = {
},
ios: {
buildConfiguration: 'Debug',
resourceClass: ResourceClass.M1_MEDIUM,
},
},
preview: {
distribution: 'internal',
ios: {
resourceClass: ResourceClass.M1_MEDIUM,
},
},
production: {
ios: {
resourceClass: ResourceClass.M1_MEDIUM,
},
},
production: {},
},
submit: {
production: {},
+10
View File
@@ -4,6 +4,7 @@ import {
BuildCredentialsSource,
BuildIosEnterpriseProvisioning,
BuildMetadataInput,
BuildMode,
BuildWorkflow,
DistributionType,
ProjectArchiveSourceInput,
@@ -34,6 +35,7 @@ export function transformProjectArchive(archiveSource: ArchiveSource): ProjectAr
export function transformMetadata(metadata: Metadata): BuildMetadataInput {
return {
...metadata,
buildMode: metadata.buildMode && transformBuildMode(metadata.buildMode),
credentialsSource:
metadata.credentialsSource && transformCredentialsSource(metadata.credentialsSource),
distribution: metadata.distribution && transformDistribution(metadata.distribution),
@@ -81,3 +83,11 @@ export function transformIosEnterpriseProvisioning(
return BuildIosEnterpriseProvisioning.Universal;
}
}
export function transformBuildMode(buildMode: Metadata['buildMode']): BuildMode {
if (buildMode === 'build') {
return BuildMode.Build;
} else {
return BuildMode.Resign;
}
}
@@ -1,5 +1,7 @@
import { Platform } from '@expo/eas-build-job';
import { BuildProfile } from '@expo/eas-json';
import { CredentialsContext } from '../../credentials/context';
import IosCredentialsProvider from '../../credentials/ios/IosCredentialsProvider';
import { getAppFromContextAsync } from '../../credentials/ios/actions/BuildCredentialsUtils';
import { IosCredentials, Target } from '../../credentials/ios/types';
@@ -31,6 +33,27 @@ export async function ensureIosCredentialsAsync(
};
}
export async function ensureIosCredentialsForBuildResignAsync(
credentialsCtx: CredentialsContext,
targets: Target[],
buildProfile: BuildProfile<Platform.IOS>
): Promise<CredentialsResult<IosCredentials>> {
const provider = new IosCredentialsProvider(credentialsCtx, {
app: await getAppFromContextAsync(credentialsCtx),
targets,
distribution: 'internal',
enterpriseProvisioning: buildProfile.enterpriseProvisioning,
});
const { credentialsSource } = buildProfile;
logCredentialsSource(credentialsSource, Platform.IOS);
return {
credentials: await provider.getCredentialsAsync(credentialsSource),
source: credentialsSource,
};
}
function shouldProvideCredentials(buildCtx: BuildContext<Platform.IOS>): boolean {
return !buildCtx.buildProfile.simulator;
}
+2 -2
View File
@@ -8,7 +8,7 @@ export function transformJob(job: Ios.Job): IosJobInput {
return {
type: transformWorkflow(job.type),
projectArchive: transformProjectArchive(job.projectArchive),
projectRootDirectory: job.projectRootDirectory,
projectRootDirectory: nullthrows(job.projectRootDirectory),
releaseChannel: job.releaseChannel,
updates: job.updates,
secrets: transformIosSecrets(job.secrets),
@@ -26,7 +26,7 @@ export function transformJob(job: Ios.Job): IosJobInput {
};
}
function transformIosSecrets(secrets: {
export function transformIosSecrets(secrets: {
buildCredentials?: Ios.BuildCredentials;
}): IosJobSecretsInput {
const buildCredentials: IosJobSecretsInput['buildCredentials'] = [];
+29 -1
View File
@@ -1,8 +1,18 @@
import { ArchiveSource, Ios, Job, Platform, sanitizeJob } from '@expo/eas-build-job';
import {
ArchiveSource,
BuildMode,
BuildTrigger,
Ios,
Job,
Platform,
sanitizeJob,
} from '@expo/eas-build-job';
import nullthrows from 'nullthrows';
import path from 'path';
import slash from 'slash';
import { IosCredentials, TargetCredentials } from '../../credentials/ios/types';
import { IosJobSecretsInput } from '../../graphql/generated';
import { getUsername } from '../../project/projectUtils';
import { getVcsClient } from '../../vcs';
import { BuildContext } from '../context';
@@ -75,10 +85,28 @@ export async function prepareJobAsync(
experimental: {
prebuildCommand: ctx.buildProfile.prebuildCommand,
},
mode: BuildMode.BUILD,
triggeredBy: BuildTrigger.EAS_CLI,
};
return sanitizeJob(job);
}
export function prepareCredentialsToResign(credentials: IosCredentials): IosJobSecretsInput {
const buildCredentials: IosJobSecretsInput['buildCredentials'] = [];
for (const targetName of Object.keys(credentials ?? {})) {
buildCredentials.push({
targetName,
provisioningProfileBase64: nullthrows(credentials?.[targetName].provisioningProfile),
distributionCertificate: {
dataBase64: nullthrows(credentials?.[targetName].distributionCertificate.certificateP12),
password: nullthrows(credentials?.[targetName].distributionCertificate.certificatePassword),
},
});
}
return { buildCredentials };
}
function prepareTargetCredentials(targetCredentials: TargetCredentials): Ios.TargetCredentials {
return {
provisioningProfileBase64: targetCredentials.provisioningProfile,
+19 -1
View File
@@ -8,8 +8,26 @@ import { ora } from '../ora';
const PLUGIN_PACKAGE_NAME = 'eas-cli-local-build-plugin';
const PLUGIN_PACKAGE_VERSION = '0.0.120';
export enum LocalBuildMode {
/**
* Local build that users can run on their own machines. Instead
* of sending build request to EAS Servers it's passing it as an argument
* to local-build-plugin, that will run the build locally.
*
* Triggered when running `eas build --local`.
*/
LOCAL_BUILD_PLUGIN,
/**
* Type of local build that is not accessible to users directly. When
* cloud build is triggered by git based integration, we are running
* in this mode. Instead of sending build request to EAS Servers it's
* printing it to the stdout as JSON, so EAS Build worker can read it.
*/
INTERNAL,
}
export interface LocalBuildOptions {
enable: boolean;
localBuildMode?: LocalBuildMode;
skipCleanup?: boolean;
skipNativeBuild?: boolean;
artifactsDir?: string;
+72 -68
View File
@@ -5,10 +5,12 @@ import { PaginatedQueryOptions } from '../commandUtils/pagination';
import { AppPlatform, BuildFilter, BuildFragment } from '../graphql/generated';
import { BuildQuery } from '../graphql/queries/BuildQuery';
import Log from '../log';
import { promptAsync } from '../prompts';
import { fromNow } from '../utils/date';
import { printJsonOnlyOutput } from '../utils/json';
import { paginatedQueryWithConfirmPromptAsync } from '../utils/queries';
import {
paginatedQueryWithConfirmPromptAsync,
paginatedQueryWithSelectPromptAsync,
} from '../utils/queries';
import { formatGraphQLBuild } from './utils/formatBuild';
export const BUILDS_LIMIT = 50;
@@ -55,82 +57,84 @@ export async function listAndRenderBuildsOnAppAsync(
}
}
function formatBuildChoiceValue(value: string | undefined | null): string {
return value ? chalk.bold(value) : chalk.dim('Unknown');
}
function formatBuildChoiceTitleAndDescription(build: BuildFragment): {
title: string;
description: string;
} {
const splitCommitMessage = build.gitCommitMessage?.split('\n');
const formattedCommitData =
build.gitCommitHash && splitCommitMessage && splitCommitMessage.length > 0
? `${chalk.dim(build.gitCommitHash.slice(0, 7))} "${chalk.bold(
splitCommitMessage[0] + (splitCommitMessage.length > 1 ? '…' : '')
)}"`
: 'Unknown';
return {
title: `ID: ${chalk.dim(build.id)} (${chalk.dim(`${fromNow(new Date(build.updatedAt))} ago`)})`,
description: [
`\tVersion: ${formatBuildChoiceValue(build.appVersion)}`,
`\t${
build.platform === AppPlatform.Ios ? 'Build number' : 'Version code'
}: ${formatBuildChoiceValue(build.appBuildVersion)}`,
`\tCommit: ${formattedCommitData}`,
].join('\n'),
};
}
export async function listAndSelectBuildsOnAppAsync(
export async function listAndSelectBuildOnAppAsync(
graphqlClient: ExpoGraphqlClient,
selectedPlatform: AppPlatform,
{
projectId,
projectDisplayName,
title,
filter,
queryOptions,
paginatedQueryOptions,
selectPromptDisabledFunction,
warningMessage,
selectPromptWarningMessage,
}: {
projectId: string;
projectDisplayName: string;
title: string;
filter?: BuildFilter;
queryOptions: PaginatedQueryOptions;
paginatedQueryOptions: PaginatedQueryOptions;
selectPromptDisabledFunction?: (build: BuildFragment) => boolean;
warningMessage?: string;
selectPromptWarningMessage?: string;
}
): Promise<BuildFragment> {
const builds = await BuildQuery.viewBuildsOnAppAsync(graphqlClient, {
appId: projectId,
limit: queryOptions.limit ?? BUILDS_LIMIT,
offset: queryOptions.offset,
filter,
});
if (builds.length === 0) {
throw new Error('Found no builds matching the provided criteria.');
): Promise<BuildFragment | null> {
if (paginatedQueryOptions.nonInteractive) {
throw new Error('Unable to select a build in non-interactive mode.');
} else {
const selectedBuild = await paginatedQueryWithSelectPromptAsync({
limit: paginatedQueryOptions.limit ?? BUILDS_LIMIT,
offset: paginatedQueryOptions.offset,
queryToPerform: (limit, offset) =>
BuildQuery.viewBuildsOnAppAsync(graphqlClient, {
appId: projectId,
limit,
offset,
filter,
}),
promptOptions: {
title,
getIdentifierForQueryItem: build => build.id,
makePartialChoiceObject: createBuildToPartialChoiceMaker(selectPromptDisabledFunction),
selectPromptWarningMessage,
},
});
return selectedBuild ?? null;
}
}
const { selectedSimulatorBuild } = await promptAsync({
type: 'select',
message: `Select ${selectedPlatform === AppPlatform.Ios ? 'iOS' : 'Android'} ${
selectedPlatform === AppPlatform.Ios ? 'simulator' : 'emulator'
} build to run for ${projectDisplayName} app`,
name: 'selectedSimulatorBuild',
choices: builds.map(build => {
const buildChoice = formatBuildChoiceTitleAndDescription(build);
return {
title: buildChoice.title,
description: buildChoice.description,
value: build,
disabled: selectPromptDisabledFunction?.(build),
};
}),
warn: warningMessage,
});
return selectedSimulatorBuild;
function formatBuildChoiceValue(value: string | undefined | null): string {
return value ? chalk.bold(value) : 'Unknown';
}
function createBuildToPartialChoiceMaker(
selectPromptDisabledFunction?: (build: BuildFragment) => boolean
) {
return (
build: BuildFragment
): {
title: string;
description: string;
disabled?: boolean;
} => {
const splitCommitMessage = build.gitCommitMessage?.split('\n');
const formattedCommitData =
build.gitCommitHash && splitCommitMessage && splitCommitMessage.length > 0
? `${build.gitCommitHash.slice(0, 7)} "${chalk.bold(
splitCommitMessage[0] + (splitCommitMessage.length > 1 ? '…' : '')
)}"`
: 'Unknown';
return {
title: `${chalk.bold(`ID:`)} ${build.id} (${chalk.bold(
`${fromNow(new Date(build.completedAt))} ago`
)})`,
description: [
`\t${chalk.bold(`Version:`)} ${formatBuildChoiceValue(build.appVersion)}`,
`\t${chalk.bold(
build.platform === AppPlatform.Ios ? 'Build number:' : 'Version code:'
)} ${formatBuildChoiceValue(build.appBuildVersion)}`,
`\t${chalk.bold(`Commit:`)} ${formattedCommitData}`,
].join('\n'),
disabled: selectPromptDisabledFunction?.(build),
};
};
}
export async function getLatestBuildAsync(
@@ -142,7 +146,7 @@ export async function getLatestBuildAsync(
projectId: string;
filter?: BuildFilter;
}
): Promise<BuildFragment> {
): Promise<BuildFragment | null> {
const builds = await BuildQuery.viewBuildsOnAppAsync(graphqlClient, {
appId: projectId,
limit: 1,
@@ -151,7 +155,7 @@ export async function getLatestBuildAsync(
});
if (builds.length === 0) {
throw new Error('Found no build matching the provided criteria.');
return null;
}
return builds[0];
+67 -30
View File
@@ -5,6 +5,7 @@ import {
EasJson,
EasJsonAccessor,
EasJsonUtils,
ResourceClass,
SubmitProfile,
} from '@expo/eas-json';
import assert from 'assert';
@@ -62,7 +63,6 @@ import { BuildContext } from './context';
import { createBuildContextAsync } from './createContext';
import { prepareIosBuildAsync } from './ios/build';
import { LocalBuildOptions } from './local';
import { UserInputResourceClass } from './types';
import { ensureExpoDevClientInstalledForDevClientBuildsAsync } from './utils/devClient';
import { printBuildResults, printLogsUrls } from './utils/printBuildInfo';
import { ensureRepoIsCleanAsync } from './utils/repository';
@@ -80,45 +80,83 @@ export interface BuildFlags {
autoSubmit: boolean;
submitProfile?: string;
localBuildOptions: LocalBuildOptions;
userInputResourceClass?: UserInputResourceClass;
resourceClass?: ResourceClass;
message?: string;
}
const iosUserInputResourceClassToBuildResourceClassMapping: Record<
UserInputResourceClass,
BuildResourceClass
> = {
[UserInputResourceClass.DEFAULT]: BuildResourceClass.IosDefault,
[UserInputResourceClass.LARGE]: BuildResourceClass.IosLarge,
[UserInputResourceClass.M1_EXPERIMENTAL]: BuildResourceClass.IosM1Large,
const iosResourceClassToBuildResourceClassMapping: Record<ResourceClass, BuildResourceClass> = {
[ResourceClass.DEFAULT]: BuildResourceClass.IosDefault,
[ResourceClass.LARGE]: BuildResourceClass.IosLarge,
[ResourceClass.M1_EXPERIMENTAL]: BuildResourceClass.IosM1Large,
[ResourceClass.M1_MEDIUM]: BuildResourceClass.IosM1Medium,
[ResourceClass.M1_LARGE]: BuildResourceClass.IosM1Large,
[ResourceClass.INTEL_MEDIUM]: BuildResourceClass.IosIntelMedium,
[ResourceClass.MEDIUM]: BuildResourceClass.IosMedium,
};
const androidUserInputResourceClassToBuildResourceClassMapping: Record<
Exclude<UserInputResourceClass, UserInputResourceClass.M1_EXPERIMENTAL>,
const androidResourceClassToBuildResourceClassMapping: Record<
Exclude<
ResourceClass,
| ResourceClass.M1_EXPERIMENTAL
| ResourceClass.M1_MEDIUM
| ResourceClass.M1_LARGE
| ResourceClass.INTEL_MEDIUM
>,
BuildResourceClass
> = {
[UserInputResourceClass.DEFAULT]: BuildResourceClass.AndroidDefault,
[UserInputResourceClass.LARGE]: BuildResourceClass.AndroidLarge,
[ResourceClass.DEFAULT]: BuildResourceClass.AndroidDefault,
[ResourceClass.LARGE]: BuildResourceClass.AndroidLarge,
[ResourceClass.MEDIUM]: BuildResourceClass.AndroidMedium,
};
function resolveResourceClass(
platform: Platform,
resourceClassInput: UserInputResourceClass
function resolveBuildResourceClass(
profile: ProfileData<'build'>,
resourceClassFlag?: ResourceClass
): BuildResourceClass {
if (platform !== Platform.IOS && resourceClassInput === UserInputResourceClass.M1_EXPERIMENTAL) {
throw new Error(
`Resource class ${UserInputResourceClass.M1_EXPERIMENTAL} is only available for iOS builds`
if (
profile.platform !== Platform.IOS &&
resourceClassFlag &&
[
ResourceClass.M1_EXPERIMENTAL,
ResourceClass.M1_MEDIUM,
ResourceClass.M1_LARGE,
ResourceClass.INTEL_MEDIUM,
].includes(resourceClassFlag)
) {
throw new Error(`Resource class ${resourceClassFlag} is only available for iOS builds`);
}
const profileResourceClass = profile.profile.resourceClass;
if (profileResourceClass && resourceClassFlag && resourceClassFlag !== profileResourceClass) {
Log.warn(
`Build profile specifies the "${profileResourceClass}" resource class but you passed "${resourceClassFlag}" to --resource-class.\nUsing the "${resourceClassFlag}" as the override.`
);
}
const resourceClass = resourceClassFlag ?? profileResourceClass ?? ResourceClass.DEFAULT;
if (profile.platform === Platform.IOS && resourceClass === ResourceClass.M1_EXPERIMENTAL) {
Log.warn(`Resource class ${chalk.bold('m1-experimental')} is deprecated.`);
}
if (
profile.platform === Platform.IOS &&
[ResourceClass.LARGE, ResourceClass.M1_LARGE].includes(resourceClass)
) {
Log.warn(
`Large resource classes are not available for iOS builds yet. Your build will use the medium resource class.`
);
}
return platform === Platform.ANDROID
? androidUserInputResourceClassToBuildResourceClassMapping[
resourceClassInput as Exclude<
UserInputResourceClass,
UserInputResourceClass.M1_EXPERIMENTAL
return profile.platform === Platform.ANDROID
? androidResourceClassToBuildResourceClassMapping[
resourceClass as Exclude<
ResourceClass,
| ResourceClass.M1_EXPERIMENTAL
| ResourceClass.M1_MEDIUM
| ResourceClass.M1_LARGE
| ResourceClass.INTEL_MEDIUM
>
]
: iosUserInputResourceClassToBuildResourceClassMapping[resourceClassInput];
: iosResourceClassToBuildResourceClassMapping[resourceClass];
}
export async function runBuildAndSubmitAsync(
@@ -170,10 +208,7 @@ export async function runBuildAndSubmitAsync(
flags,
moreBuilds: platforms.length > 1,
buildProfile,
resourceClass: resolveResourceClass(
buildProfile.platform,
flags.userInputResourceClass ?? UserInputResourceClass.DEFAULT
),
resourceClass: resolveBuildResourceClass(buildProfile, flags.resourceClass),
easJsonCliConfig,
actor,
graphqlClient,
@@ -186,7 +221,7 @@ export async function runBuildAndSubmitAsync(
buildCtxByPlatform[toAppPlatform(buildProfile.platform)] = buildCtx;
}
if (flags.localBuildOptions.enable) {
if (flags.localBuildOptions.localBuildMode) {
return;
}
@@ -240,6 +275,8 @@ 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);
-10
View File
@@ -12,13 +12,3 @@ export enum BuildDistributionType {
INTERNAL = 'internal',
SIMULATOR = 'simulator',
}
export enum UserInputResourceClass {
DEFAULT = 'default',
LARGE = 'large',
/**
* @experimental
* This resource class is not yet ready to be used in production. For testing purposes only. Might be deprecated / deleted at any time.
*/
M1_EXPERIMENTAL = 'm1-experimental',
}
@@ -1,5 +1,4 @@
import assert from 'assert';
import chalk from 'chalk';
import indentString from 'indent-string';
import qrcodeTerminal from 'qrcode-terminal';
@@ -12,20 +11,20 @@ import {
EasBuildDeprecationInfo,
EasBuildDeprecationInfoType,
} from '../../graphql/generated';
import Log, { learnMore } from '../../log';
import Log, { learnMore, link } from '../../log';
import { appPlatformDisplayNames, appPlatformEmojis } from '../../platform';
import { getBuildLogsUrl, getInternalDistributionInstallUrl } from './url';
export function printLogsUrls(builds: BuildFragment[]): void {
if (builds.length === 1) {
Log.log(`Build details: ${chalk.underline(getBuildLogsUrl(builds[0]))}`);
Log.log(`Build details: ${link(getBuildLogsUrl(builds[0]))}`);
} else {
builds.forEach(build => {
const logsUrl = getBuildLogsUrl(build);
Log.log(
`${appPlatformEmojis[build.platform]} ${
appPlatformDisplayNames[build.platform]
} build details: ${chalk.underline(logsUrl)}`
} build details: ${link(logsUrl)}`
);
});
}
@@ -79,13 +78,13 @@ function printBuildResult(build: BuildFragment): void {
appPlatformDisplayNames[build.platform]
} devices (or scan the QR code) to install the app:`
);
Log.log(`${chalk.underline(logsUrl)}`);
Log.log(`${link(logsUrl)}`);
} else {
// TODO: it looks like buildUrl could possibly be undefined, based on the code below.
// we should account for this case better if it is possible
const url = build.artifacts?.buildUrl ?? '';
Log.log(`${appPlatformEmojis[build.platform]} ${appPlatformDisplayNames[build.platform]} app:`);
Log.log(`${chalk.underline(url)}`);
Log.log(`${link(url)}`);
}
}
+5
View File
@@ -0,0 +1,5 @@
export class ChannelNotFoundError extends Error {
constructor(message?: string) {
super(message ?? 'Channel not found.');
}
}
+1 -1
View File
@@ -46,7 +46,7 @@ export async function selectChannelOnAppAsync(
queryChannelsOnAppAsync(graphqlClient, { appId: projectId, limit, offset }),
promptOptions: {
title: selectionPromptTitle,
createDisplayTextForSelectionPromptListItem: updateChannel => updateChannel.name,
makePartialChoiceObject: updateChannel => ({ title: updateChannel.name }),
getIdentifierForQueryItem: updateChannel => updateChannel.id,
},
});
@@ -59,7 +59,7 @@ describe(EasCommand.name, () => {
const sessionManagerSpy = jest.spyOn(SessionManager.prototype, 'getUserAsync');
expect(sessionManagerSpy).toBeCalledTimes(1);
}, 15_000);
}, 30_000);
it('initializes analytics', async () => {
const TestEasCommand = createTestEasCommand();
@@ -132,6 +132,8 @@ export async function getProjectIdAsync(
throw new Error(
'The "owner" manifest property is required when using robot users. See: https://docs.expo.dev/versions/latest/config/app/#owner'
);
case 'SSOUser':
throw new Error('SSO users are not supported yet.');
}
};
@@ -120,7 +120,7 @@ export default class BranchDelete extends EasCommand {
}
({ name: branchName } = await selectBranchOnAppAsync(graphqlClient, {
projectId,
displayTextForListItem: updateBranch => updateBranch.name,
displayTextForListItem: updateBranch => ({ title: updateBranch.name }),
promptTitle: 'Which branch would you like to delete?',
paginatedQueryOptions,
}));
+3 -1
View File
@@ -57,7 +57,9 @@ export default class BranchView extends EasCommand {
({ name: branchName } = await selectBranchOnAppAsync(graphqlClient, {
projectId,
promptTitle: 'Which branch would you like to view?',
displayTextForListItem: updateBranch => updateBranch.name,
displayTextForListItem: updateBranch => ({
title: updateBranch.name,
}),
// discard limit and offset because this query is not their intended target
paginatedQueryOptions: {
json: paginatedQueryOptions.json,
+15 -23
View File
@@ -1,13 +1,13 @@
import { Platform } from '@expo/eas-build-job';
import { EasJsonAccessor, EasJsonUtils } from '@expo/eas-json';
import { EasJsonAccessor, EasJsonUtils, ResourceClass } from '@expo/eas-json';
import { Errors, Flags } from '@oclif/core';
import chalk from 'chalk';
import figures from 'figures';
import fs from 'fs-extra';
import path from 'path';
import { LocalBuildMode } from '../../build/local';
import { BuildFlags, runBuildAndSubmitAsync } from '../../build/runBuildAndSubmit';
import { UserInputResourceClass } from '../../build/types';
import EasCommand from '../../commandUtils/EasCommand';
import { EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
import { StatuspageServiceName } from '../../graphql/generated';
@@ -31,7 +31,7 @@ interface RawBuildFlags {
json: boolean;
'auto-submit': boolean;
'auto-submit-with-profile'?: string;
'resource-class'?: UserInputResourceClass;
'resource-class'?: ResourceClass;
message?: string;
}
@@ -85,8 +85,13 @@ export default class Build extends EasCommand {
exclusive: ['auto-submit'],
}),
'resource-class': Flags.enum({
options: Object.values(UserInputResourceClass),
options: Object.values(ResourceClass),
hidden: true,
deprecated: {
message: chalk.yellow(
'The --resource-class flag has been deprecated. Define the resource class in eas.json.\nLearn more: https://docs.expo.dev/build-reference/eas-json/'
),
},
description: 'The instance type that will be used to run this build [experimental]',
}),
message: Flags.string({
@@ -122,7 +127,7 @@ export default class Build extends EasCommand {
await handleDeprecatedEasJsonAsync(projectDir, flags.nonInteractive);
if (!flags.localBuildOptions.enable) {
if (!flags.localBuildOptions.localBuildMode) {
await maybeWarnAboutEasOutagesAsync(
graphqlClient,
flags.autoSubmit
@@ -156,17 +161,6 @@ export default class Build extends EasCommand {
if (flags.json && !nonInteractive) {
Errors.error('--json is allowed only when building in non-interactive mode', { exit: 1 });
}
if (
flags['resource-class'] === UserInputResourceClass.M1_EXPERIMENTAL &&
flags.platform !== Platform.IOS
) {
Errors.error(
`Resource class ${UserInputResourceClass.M1_EXPERIMENTAL} is only available for iOS builds`,
{
exit: 1,
}
);
}
const requestedPlatform =
flags.platform &&
@@ -201,19 +195,17 @@ export default class Build extends EasCommand {
nonInteractive,
localBuildOptions: flags['local']
? {
enable: true,
localBuildMode: LocalBuildMode.LOCAL_BUILD_PLUGIN,
verbose: true,
artifactPath: flags.output && path.resolve(process.cwd(), flags.output),
}
: {
enable: false,
},
: {},
wait: flags['wait'],
clearCache: flags['clear-cache'],
json: flags['json'],
autoSubmit: flags['auto-submit'] || flags['auto-submit-with-profile'] !== undefined,
submitProfile: flags['auto-submit-with-profile'] ?? profile,
userInputResourceClass: flags['resource-class'] ?? UserInputResourceClass.DEFAULT,
resourceClass: flags['resource-class'],
message,
};
}
@@ -223,7 +215,7 @@ export default class Build extends EasCommand {
): Promise<BuildFlags> {
const requestedPlatform = await selectRequestedPlatformAsync(flags.requestedPlatform);
if (flags.localBuildOptions.enable) {
if (flags.localBuildOptions.localBuildMode) {
if (flags.autoSubmit) {
// TODO: implement this
Errors.error('Auto-submits are not yet supported when building locally', { exit: 1 });
@@ -245,7 +237,7 @@ export default class Build extends EasCommand {
}
}
async function handleDeprecatedEasJsonAsync(
export async function handleDeprecatedEasJsonAsync(
projectDir: string,
nonInteractive: boolean
): Promise<void> {
@@ -4,6 +4,7 @@ import fs from 'fs-extra';
import path from 'path';
import { v4 as uuidv4 } from 'uuid';
import { LocalBuildMode } from '../../build/local';
import { runBuildAndSubmitAsync } from '../../build/runBuildAndSubmit';
import EasCommand from '../../commandUtils/EasCommand';
import Log from '../../log';
@@ -110,7 +111,7 @@ export default class BuildInspect extends EasCommand {
requestedPlatform: flags.platform,
profile: flags.profile,
localBuildOptions: {
enable: true,
localBuildMode: LocalBuildMode.LOCAL_BUILD_PLUGIN,
...(flags.stage === InspectStage.PRE_BUILD ? { skipNativeBuild: true } : {}),
...(flags.stage === InspectStage.POST_BUILD ? { skipCleanup: true } : {}),
verbose: flags.verbose,
@@ -0,0 +1,76 @@
import { Flags } from '@oclif/core';
import { handleDeprecatedEasJsonAsync } from '.';
import { LocalBuildMode } from '../../build/local';
import { runBuildAndSubmitAsync } from '../../build/runBuildAndSubmit';
import EasCommand from '../../commandUtils/EasCommand';
import { RequestedPlatform } from '../../platform';
import { enableJsonOutput } from '../../utils/json';
/**
* This command will be run on the EAS Build workers, when building
* directly from git. This command resolves credentials and other
* build configuration, that normally would be included in the
* job and metadata objects, and prints them to stdout.
*/
export default class BuildInternal extends EasCommand {
static override hidden = true;
static override flags = {
platform: Flags.enum({
char: 'p',
options: ['android', 'ios'],
required: true,
}),
profile: Flags.string({
char: 'e',
description:
'Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.',
helpValue: 'PROFILE_NAME',
}),
};
static override contextDefinition = {
...this.ContextOptions.LoggedIn,
...this.ContextOptions.DynamicProjectConfig,
...this.ContextOptions.ProjectDir,
...this.ContextOptions.Analytics,
};
async runAsync(): Promise<void> {
const { flags } = await this.parse(BuildInternal);
// This command is always run with implicit --non-interactive and --json options
enableJsonOutput();
const {
loggedIn: { actor, graphqlClient },
getDynamicProjectConfigAsync,
projectDir,
analytics,
} = await this.getContextAsync(BuildInternal, {
nonInteractive: true,
});
await handleDeprecatedEasJsonAsync(projectDir, flags.nonInteractive);
await runBuildAndSubmitAsync(
graphqlClient,
analytics,
projectDir,
{
requestedPlatform: flags.platform as RequestedPlatform,
profile: flags.profile,
nonInteractive: true,
wait: false,
clearCache: false,
json: true,
autoSubmit: false,
localBuildOptions: {
localBuildMode: LocalBuildMode.INTERNAL,
},
},
actor,
getDynamicProjectConfigAsync
);
}
}
@@ -0,0 +1,298 @@
import { Platform } from '@expo/eas-build-job';
import { CredentialsSource, EasJson, EasJsonAccessor, EasJsonUtils } from '@expo/eas-json';
import { Flags } from '@oclif/core';
import assert from 'assert';
import chalk from 'chalk';
import { handleDeprecatedEasJsonAsync } from '.';
import { waitForBuildEndAsync } from '../../build/build';
import { ensureIosCredentialsForBuildResignAsync } from '../../build/ios/credentials';
import { prepareCredentialsToResign } from '../../build/ios/prepareJob';
import { listAndSelectBuildOnAppAsync } from '../../build/queries';
import { printBuildResults, printLogsUrls } from '../../build/utils/printBuildInfo';
import EasCommand from '../../commandUtils/EasCommand';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
import { EasPaginatedQueryFlags } from '../../commandUtils/pagination';
import { CredentialsContext } from '../../credentials/context';
import {
BuildFragment,
BuildMode,
BuildStatus,
BuildWorkflow,
DistributionType,
IosJobOverridesInput,
ProjectArchiveSourceType,
StatuspageServiceName,
} from '../../graphql/generated';
import { BuildMutation } from '../../graphql/mutations/BuildMutation';
import { BuildQuery } from '../../graphql/queries/BuildQuery';
import { toAppPlatform } from '../../graphql/types/AppPlatform';
import Log from '../../log';
import { requestedPlatformDisplayNames, selectPlatformAsync } from '../../platform';
import { resolveXcodeBuildContextAsync } from '../../project/ios/scheme';
import { resolveTargetsAsync } from '../../project/ios/target';
import { getOwnerAccountForProjectIdAsync } from '../../project/projectUtils';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
import { maybeWarnAboutEasOutagesAsync } from '../../utils/statuspageService';
interface BuildResignFlags {
json: boolean;
nonInteractive: boolean;
offset?: number;
limit?: number;
platform?: Platform;
profile?: string;
maybeBuildId?: string;
wait: boolean;
}
interface RawBuildResignFlags {
json: boolean;
'non-interactive': boolean;
offset: number | undefined;
limit: number | undefined;
platform: 'android' | 'ios' | undefined;
profile: string | undefined;
wait: boolean;
id: string | undefined;
}
export default class BuildResign extends EasCommand {
static override description = 're-sign a build archive';
static override flags = {
platform: Flags.enum({
char: 'p',
options: ['android', 'ios'],
}),
profile: Flags.string({
char: 'e',
description:
'Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.',
helpValue: 'PROFILE_NAME',
}),
wait: Flags.boolean({
default: true,
allowNo: true,
description: 'Wait for build(s) to complete.',
}),
id: Flags.string({
description: 'ID of the build to re-sign.',
}),
...EasPaginatedQueryFlags,
...EasNonInteractiveAndJsonFlags,
};
static override contextDefinition = {
...this.ContextOptions.LoggedIn,
...this.ContextOptions.DynamicProjectConfig,
...this.ContextOptions.ProjectDir,
...this.ContextOptions.Analytics,
};
async runAsync(): Promise<void> {
const { flags: rawFlags } = await this.parse(BuildResign);
if (rawFlags.json) {
enableJsonOutput();
}
const flags = this.sanitizeFlags(rawFlags as RawBuildResignFlags);
const { limit, offset, nonInteractive } = flags;
const {
loggedIn: { actor, graphqlClient },
getDynamicProjectConfigAsync,
projectDir,
analytics,
} = await this.getContextAsync(BuildResign, {
nonInteractive: flags.nonInteractive,
});
const maybeBuild = flags.maybeBuildId
? await this.maybeGetBuildAsync(graphqlClient, flags.maybeBuildId)
: undefined;
const platform =
(maybeBuild?.platform.toLowerCase() as Platform | undefined) ??
(await selectPlatformAsync(flags.platform));
if (platform === Platform.ANDROID) {
throw new Error('Re-signing archives is not supported on Android yet.');
}
await handleDeprecatedEasJsonAsync(projectDir, flags.nonInteractive);
await maybeWarnAboutEasOutagesAsync(graphqlClient, [StatuspageServiceName.EasBuild]);
const easJsonAccessor = new EasJsonAccessor(projectDir);
const easJsonCliConfig: EasJson['cli'] =
(await EasJsonUtils.getCliConfigAsync(easJsonAccessor)) ?? {};
const buildProfile = await EasJsonUtils.getBuildProfileAsync(
easJsonAccessor,
platform,
flags.profile ?? 'production'
);
const { exp, projectId } = await getDynamicProjectConfigAsync({ env: buildProfile.env });
const account = await getOwnerAccountForProjectIdAsync(graphqlClient, projectId);
const build = await this.ensureBuildSelectedAsync(
{ graphqlClient, projectId, platform, nonInteractive, limit, offset },
maybeBuild
);
const credentialsCtx = new CredentialsContext({
projectInfo: { exp, projectId },
nonInteractive,
projectDir,
user: actor,
graphqlClient,
analytics,
env: buildProfile.env,
easJsonCliConfig,
});
if (buildProfile.credentialsSource !== CredentialsSource.LOCAL && !nonInteractive) {
await credentialsCtx.appStore.ensureAuthenticatedAsync();
}
const xcodeBuildContext = await resolveXcodeBuildContextAsync(
{
projectDir,
nonInteractive,
exp,
},
buildProfile
);
const targets = await resolveTargetsAsync({
projectDir,
exp,
xcodeBuildContext,
env: buildProfile.env,
});
const credentialsResult = await ensureIosCredentialsForBuildResignAsync(
credentialsCtx,
targets,
buildProfile
);
assert(build.artifacts?.applicationArchiveUrl, 'Missing application archive.');
const jobOverrides: IosJobOverridesInput = {
mode: BuildMode.Resign,
type: BuildWorkflow.Unknown,
resign: {
applicationArchiveSource: {
type: ProjectArchiveSourceType.Url,
url: build.artifacts?.applicationArchiveUrl,
},
},
secrets: prepareCredentialsToResign(credentialsResult.credentials),
builderEnvironment: { image: 'default' },
};
const newBuild = await BuildMutation.retryIosBuildAsync(graphqlClient, {
buildId: build.id,
jobOverrides,
});
Log.addNewLineIfNone();
printLogsUrls([newBuild]);
Log.newLine();
if (!flags.wait) {
if (flags.json) {
printJsonOnlyOutput(newBuild);
}
return;
}
const buildResult = await waitForBuildEndAsync(graphqlClient, {
buildIds: [newBuild.id],
accountName: account.name,
nonInteractive,
projectDir,
});
if (!flags.json) {
printBuildResults(buildResult);
} else {
assert(buildResult[0], 'missing build results');
printJsonOnlyOutput(buildResult[0]);
}
}
sanitizeFlags(flags: RawBuildResignFlags): BuildResignFlags {
const nonInteractive = flags['non-interactive'];
if (nonInteractive && !flags.id) {
throw new Error(
`${chalk.bold('--id')} is required when running with ${chalk.bold(
'--non-interactive'
)} flag.`
);
}
return {
json: flags.json,
nonInteractive,
offset: flags.offset,
limit: flags.limit,
platform: flags.platform as Platform | undefined,
profile: flags.profile,
maybeBuildId: flags.id,
wait: flags.wait,
};
}
async ensureBuildSelectedAsync(
{
graphqlClient,
projectId,
platform,
nonInteractive,
limit,
offset,
}: {
graphqlClient: ExpoGraphqlClient;
projectId: string;
platform: Platform;
nonInteractive: boolean;
limit?: number;
offset?: number;
},
maybeBuild?: BuildFragment
): Promise<BuildFragment> {
if (maybeBuild) {
return maybeBuild;
}
const build = await listAndSelectBuildOnAppAsync(graphqlClient, {
projectId,
title: 'Which build would you like to re-sign with new credentials?',
paginatedQueryOptions: {
limit,
offset: offset ?? 0,
nonInteractive,
json: false,
},
filter: {
distribution: DistributionType.Internal,
platform: toAppPlatform(platform),
status: BuildStatus.Finished,
},
});
if (!build) {
throw new Error('There are no builds that can be re-signed on this project.');
}
return build;
}
async maybeGetBuildAsync(
graphqlClient: ExpoGraphqlClient,
maybeBuildId?: string,
maybePlatform?: Platform
): Promise<BuildFragment | undefined> {
if (maybeBuildId) {
const build = await BuildQuery.byIdAsync(graphqlClient, maybeBuildId);
if (build.distribution !== DistributionType.Internal) {
throw new Error('This is not an internal distribution build.');
}
if (build.status !== BuildStatus.Finished) {
throw new Error('Only builds that finished successfully can be re-signed.');
}
if (maybePlatform && build.platform !== toAppPlatform(maybePlatform)) {
throw new Error(
`Build with ID ${maybeBuildId} was not created for platform ${requestedPlatformDisplayNames[maybePlatform]}.`
);
}
return build;
}
return undefined;
}
}
+44 -8
View File
@@ -1,9 +1,9 @@
import { Errors, Flags } from '@oclif/core';
import assert from 'assert';
import { pathExists } from 'fs-extra';
import assert from 'node:assert';
import path from 'path';
import { getLatestBuildAsync, listAndSelectBuildsOnAppAsync } from '../../build/queries';
import { getLatestBuildAsync, listAndSelectBuildOnAppAsync } from '../../build/queries';
import EasCommand from '../../commandUtils/EasCommand';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import {
@@ -14,6 +14,7 @@ import {
import { AppPlatform, BuildFragment, BuildStatus, DistributionType } from '../../graphql/generated';
import { BuildQuery } from '../../graphql/queries/BuildQuery';
import Log from '../../log';
import { appPlatformDisplayNames } from '../../platform';
import { getDisplayNameForProjectIdAsync } from '../../project/projectUtils';
import { promptAsync } from '../../prompts';
import { RunArchiveFlags, runAsync } from '../../run/run';
@@ -150,6 +151,35 @@ async function resolvePlatformAsync(platform?: string): Promise<AppPlatform> {
return selectedPlatform;
}
function validateChosenBuild(
maybeBuild: BuildFragment | null,
selectedPlatform: AppPlatform
): BuildFragment {
if (!maybeBuild) {
throw new Error('There are no simulator/emulator builds that can be run for this project.');
}
if (selectedPlatform !== maybeBuild.platform) {
throw new Error(
`The selected build is for ${
appPlatformDisplayNames[maybeBuild.platform]
}, but you selected ${appPlatformDisplayNames[selectedPlatform]}`
);
}
if (maybeBuild.status !== BuildStatus.Finished) {
throw new Error('The selected build is not finished.');
}
if (!isRunnableOnSimulatorOrEmulator(maybeBuild)) {
throw new Error(
'Artifacts for the latest build have expired and are no longer available, or this is not a simulator/emulator build.'
);
}
return maybeBuild;
}
async function maybeGetBuildAsync(
graphqlClient: ExpoGraphqlClient,
flags: RunCommandFlags,
@@ -160,28 +190,32 @@ async function maybeGetBuildAsync(
flags.selectedPlatform === AppPlatform.Ios ? DistributionType.Simulator : undefined;
if (flags.runArchiveFlags.id) {
return BuildQuery.byIdAsync(graphqlClient, flags.runArchiveFlags.id);
const build = await BuildQuery.byIdAsync(graphqlClient, flags.runArchiveFlags.id);
return validateChosenBuild(build, flags.selectedPlatform);
} else if (
!flags.runArchiveFlags.id &&
!flags.runArchiveFlags.path &&
!flags.runArchiveFlags.url &&
!flags.runArchiveFlags.latest
) {
return await listAndSelectBuildsOnAppAsync(graphqlClient, flags.selectedPlatform, {
const build = await listAndSelectBuildOnAppAsync(graphqlClient, {
projectId,
projectDisplayName: await getDisplayNameForProjectIdAsync(graphqlClient, projectId),
title: `Select ${appPlatformDisplayNames[flags.selectedPlatform]} ${
flags.selectedPlatform === AppPlatform.Ios ? 'simulator' : 'emulator'
} build to run for ${await getDisplayNameForProjectIdAsync(graphqlClient, projectId)} app`,
filter: {
platform: flags.selectedPlatform,
distribution: distributionType,
status: BuildStatus.Finished,
},
queryOptions: paginatedQueryOptions,
paginatedQueryOptions,
selectPromptDisabledFunction: build => !isRunnableOnSimulatorOrEmulator(build),
warningMessage:
selectPromptWarningMessage:
'Artifacts for this build have expired and are no longer available, or this is not a simulator/emulator build.',
});
return validateChosenBuild(build, flags.selectedPlatform);
} else if (flags.runArchiveFlags.latest) {
return await getLatestBuildAsync(graphqlClient, {
const latestBuild = await getLatestBuildAsync(graphqlClient, {
projectId,
filter: {
platform: flags.selectedPlatform,
@@ -189,6 +223,8 @@ async function maybeGetBuildAsync(
status: BuildStatus.Finished,
},
});
return validateChosenBuild(latestBuild, flags.selectedPlatform);
} else {
return null;
}
@@ -107,7 +107,7 @@ export default class ChannelEdit extends EasCommand {
: await selectBranchOnAppAsync(graphqlClient, {
projectId,
promptTitle: `Which branch would you like ${existingChannel.name} to point at?`,
displayTextForListItem: updateBranch => updateBranch.name,
displayTextForListItem: updateBranch => ({ title: updateBranch.name }),
paginatedQueryOptions: {
json,
nonInteractive,
+41 -15
View File
@@ -5,10 +5,12 @@ import { Flags } from '@oclif/core';
import chalk from 'chalk';
import EasCommand from '../commandUtils/EasCommand';
import { EasNonInteractiveAndJsonFlags } from '../commandUtils/flags';
import { toAppPlatform } from '../graphql/types/AppPlatform';
import Log from '../log';
import { appPlatformEmojis } from '../platform';
import { selectAsync } from '../prompts';
import { enableJsonOutput, printJsonOnlyOutput } from '../utils/json';
export default class Config extends EasCommand {
static override description = 'display project configuration (app.json + eas.json)';
@@ -21,6 +23,11 @@ export default class Config extends EasCommand {
'Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.',
helpValue: 'PROFILE_NAME',
}),
// This option is used only on EAS Build worker to read build profile from eas.json.
'eas-json-only': Flags.boolean({
hidden: true,
}),
...EasNonInteractiveAndJsonFlags,
};
static override contextDefinition = {
@@ -30,6 +37,9 @@ export default class Config extends EasCommand {
async runAsync(): Promise<void> {
const { flags } = await this.parse(Config);
if (flags.json) {
enableJsonOutput();
}
const { platform: maybePlatform, profile: maybeProfile } = flags;
const { getDynamicProjectConfigAsync, projectDir } = await this.getContextAsync(Config, {
nonInteractive: false,
@@ -61,21 +71,37 @@ export default class Config extends EasCommand {
]));
const profile = await EasJsonUtils.getBuildProfileAsync(accessor, platform, profileName);
const { exp: config } = await getDynamicProjectConfigAsync({
env: profile.env,
isPublicConfig: true,
});
if (flags['eas-json-only']) {
if (flags.json) {
printJsonOnlyOutput({ buildProfile: profile });
} else {
const appPlatform = toAppPlatform(platform);
const platformEmoji = appPlatformEmojis[appPlatform];
Log.log(`${platformEmoji} ${chalk.bold(`Build profile "${profileName}"`)}`);
Log.newLine();
Log.log(JSON.stringify(profile, null, 2));
}
} else {
const { exp: appConfig } = await getDynamicProjectConfigAsync({
env: profile.env,
isPublicConfig: true,
});
Log.addNewLineIfNone();
Log.log(chalk.bold(getProjectConfigDescription(projectDir)));
Log.newLine();
Log.log(JSON.stringify(config, null, 2));
Log.newLine();
Log.newLine();
const appPlatform = toAppPlatform(platform);
const platformEmoji = appPlatformEmojis[appPlatform];
Log.log(`${platformEmoji} ${chalk.bold(`Build profile "${profileName}"`)}`);
Log.newLine();
Log.log(JSON.stringify(profile, null, 2));
if (flags.json) {
printJsonOnlyOutput({ buildProfile: profile, appConfig });
} else {
Log.addNewLineIfNone();
Log.log(chalk.bold(getProjectConfigDescription(projectDir)));
Log.newLine();
Log.log(JSON.stringify(appConfig, null, 2));
Log.newLine();
Log.newLine();
const appPlatform = toAppPlatform(platform);
const platformEmoji = appPlatformEmojis[appPlatform];
Log.log(`${platformEmoji} ${chalk.bold(`Build profile "${profileName}"`)}`);
Log.newLine();
Log.log(JSON.stringify(profile, null, 2));
}
}
}
}
@@ -3,7 +3,6 @@ import { ExpoConfig } from '@expo/config-types';
import { Flags } from '@oclif/core';
import chalk from 'chalk';
import nullthrows from 'nullthrows';
import terminalLink from 'terminal-link';
import { getProjectDashboardUrl } from '../../build/utils/url';
import EasCommand from '../../commandUtils/EasCommand';
@@ -12,7 +11,7 @@ import { saveProjectIdToAppConfigAsync } from '../../commandUtils/context/contex
import { AppPrivacy, Role } from '../../graphql/generated';
import { AppMutation } from '../../graphql/mutations/AppMutation';
import { AppQuery } from '../../graphql/queries/AppQuery';
import Log from '../../log';
import Log, { link } from '../../log';
import { ora } from '../../ora';
import { getExpoConfig } from '../../project/expoConfig';
import { findProjectIdByAccountNameAndSlugNullableAsync } from '../../project/fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync';
@@ -244,7 +243,9 @@ export default class ProjectInit extends EasCommand {
const sortedAccounts =
actor.__typename === 'Robot'
? allAccounts
: [...allAccounts].sort((a, _b) => (a.name === actor.username ? -1 : 1));
: [...allAccounts].sort((a, _b) =>
actor.__typename === 'User' ? (a.name === actor.username ? -1 : 1) : 0
);
const choices = sortedAccounts.map(account => ({
title: account.name,
@@ -303,10 +304,7 @@ export default class ProjectInit extends EasCommand {
}
const projectDashboardUrl = getProjectDashboardUrl(accountName, projectName);
const projectLink = terminalLink(projectFullName, projectDashboardUrl, {
// https://github.com/sindresorhus/terminal-link/issues/18#issuecomment-1068020361
fallback: () => `${projectFullName} (${projectDashboardUrl})`,
});
const projectLink = link(projectDashboardUrl, { text: projectFullName });
const account = nullthrows(allAccounts.find(a => a.name === accountName));
@@ -0,0 +1,254 @@
import { AppJSONConfig, PackageJSONConfig, Platform, getConfig } from '@expo/config';
import { Updates } from '@expo/config-plugins';
import { vol } from 'memfs';
import path from 'path';
import { instance, mock } from 'ts-mockito';
import UpdatePublish from '..';
import { ensureBranchExistsAsync } from '../../../branch/queries';
import { DynamicProjectConfigContextField } from '../../../commandUtils/context/DynamicProjectConfigContextField';
import LoggedInContextField from '../../../commandUtils/context/LoggedInContextField';
import { ExpoGraphqlClient } from '../../../commandUtils/context/contextUtils/createGraphqlClient';
import FeatureGateEnvOverrides from '../../../commandUtils/gating/FeatureGateEnvOverrides';
import FeatureGating from '../../../commandUtils/gating/FeatureGating';
import { jester } from '../../../credentials/__tests__/fixtures-constants';
import { UpdateFragment } from '../../../graphql/generated';
import { PublishMutation } from '../../../graphql/mutations/PublishMutation';
import { AppQuery } from '../../../graphql/queries/AppQuery';
import { collectAssetsAsync, uploadAssetsAsync } from '../../../project/publish';
import { getBranchNameFromChannelNameAsync } from '../../../update/getBranchNameFromChannelNameAsync';
const projectRoot = '/test-project';
const commandOptions = { root: projectRoot } as any;
const updateStub: UpdateFragment = {
id: 'update-1234',
group: 'group-1234',
branch: { id: 'branch-1234', name: 'main' },
message: 'test message',
runtimeVersion: 'exposdk:47.0.0',
platform: 'ios',
gitCommitHash: 'commit',
manifestFragment: JSON.stringify({ fake: 'manifest' }),
manifestPermalink: 'https://expo.dev/fake/manifest/link',
codeSigningInfo: null,
createdAt: '2022-01-01T12:00:00Z',
};
jest.mock('fs');
jest.mock('@expo/config');
jest.mock('@expo/config-plugins');
jest.mock('../../../branch/queries');
jest.mock('../../../commandUtils/context/contextUtils/getProjectIdAsync');
jest.mock('../../../update/configure');
jest.mock('../../../update/getBranchNameFromChannelNameAsync');
jest.mock('../../../graphql/mutations/PublishMutation');
jest.mock('../../../graphql/queries/AppQuery');
jest.mock('../../../graphql/queries/UpdateQuery');
jest.mock('../../../ora', () => ({
ora: () => ({
start: () => ({ succeed: () => {}, fail: () => {} }),
}),
}));
jest.mock('../../../project/publish', () => ({
...jest.requireActual('../../../project/publish'),
buildBundlesAsync: jest.fn(),
collectAssetsAsync: jest.fn(),
resolveInputDirectoryAsync: jest.fn((inputDir = 'dist') => path.join(projectRoot, inputDir)),
uploadAssetsAsync: jest.fn(),
}));
describe(UpdatePublish.name, () => {
afterEach(() => vol.reset());
// Deprecated and split to a new command: update:republish
it('errors with --republish', async () => {
await expect(new UpdatePublish(['--republish'], commandOptions).run()).rejects.toThrow(
'--group and --republish flags are deprecated'
);
});
// Deprecated and split to a new command: update:republish
it('errors with --group', async () => {
await expect(new UpdatePublish(['--group=abc123'], commandOptions).run()).rejects.toThrow(
'--group and --republish flags are deprecated'
);
});
it('errors with both --channel and --branch', async () => {
const flags = ['--channel=channel123', '--branch=branch123'];
mockTestProject();
await expect(new UpdatePublish(flags, commandOptions).run()).rejects.toThrow(
'Cannot specify both --channel and --branch. Specify either --channel, --branch, or --auto'
);
});
it('creates a new update with --non-interactive, --branch, and --message', async () => {
const flags = ['--non-interactive', '--branch=branch123', '--message=abc'];
mockTestProject();
const { platforms, runtimeVersion } = mockTestExport();
jest.mocked(ensureBranchExistsAsync).mockResolvedValue({
branchId: 'branch123',
createdBranch: false,
});
jest
.mocked(PublishMutation.publishUpdateGroupAsync)
.mockResolvedValue(platforms.map(platform => ({ ...updateStub, platform, runtimeVersion })));
await new UpdatePublish(flags, commandOptions).run();
expect(PublishMutation.publishUpdateGroupAsync).toHaveBeenCalled();
});
it('creates a new update with --non-interactive, --channel, and --message', async () => {
const flags = ['--non-interactive', '--channel=channel123', '--message=abc'];
const { projectId } = mockTestProject();
const { platforms, runtimeVersion } = mockTestExport();
jest.mocked(getBranchNameFromChannelNameAsync).mockResolvedValue('branchFromChannel');
jest.mocked(ensureBranchExistsAsync).mockResolvedValue({
branchId: 'branch123',
createdBranch: false,
});
jest.mocked(PublishMutation.publishUpdateGroupAsync).mockResolvedValue(
platforms.map(platform => ({
...updateStub,
runtimeVersion,
platform,
}))
);
await new UpdatePublish(flags, commandOptions).run();
expect(ensureBranchExistsAsync).toHaveBeenCalledWith(
expect.any(Object), // graphql client
{
appId: projectId,
branchName: 'branchFromChannel',
}
);
expect(PublishMutation.publishUpdateGroupAsync).toHaveBeenCalled();
});
});
/** Create a new in-memory project, copied from src/commands/update/__tests__/republish.test.ts */
function mockTestProject({
configuredProjectId = '1234',
}: {
configuredProjectId?: string;
} = {}): { projectId: string } {
const packageJSON: PackageJSONConfig = {
name: 'testing123',
version: '0.1.0',
description: 'fake description',
main: 'index.js',
};
const appJSON: AppJSONConfig = {
expo: {
name: 'testing 123',
version: '0.1.0',
slug: 'testing-123',
sdkVersion: '33.0.0',
owner: jester.accounts[0].name,
extra: {
eas: {
projectId: configuredProjectId,
},
},
},
};
vol.fromJSON(
{
'package.json': JSON.stringify(packageJSON),
'app.json': JSON.stringify(appJSON),
},
projectRoot
);
const mockManifest = { exp: appJSON.expo };
const graphqlClient = instance(mock<ExpoGraphqlClient>({}));
jest.mocked(getConfig).mockReturnValue(mockManifest as any);
jest
.spyOn(DynamicProjectConfigContextField.prototype, 'getValueAsync')
.mockResolvedValue(async () => ({
exp: mockManifest.exp,
projectDir: projectRoot,
projectId: configuredProjectId,
}));
jest.spyOn(LoggedInContextField.prototype, 'getValueAsync').mockResolvedValue({
actor: jester,
featureGating: new FeatureGating({}, new FeatureGateEnvOverrides()),
graphqlClient,
});
jest.mocked(AppQuery.byIdAsync).mockResolvedValue({
id: '1234',
slug: 'testing-123',
fullName: '@jester/testing-123',
ownerAccount: jester.accounts[0],
});
return { projectId: configuredProjectId };
}
/** Create a new in-memory export of the project */
function mockTestExport({
exportDir = 'dist',
platforms = ['android', 'ios'],
runtimeVersion = 'exposdk:47.0.0',
}: {
exportDir?: string;
platforms?: Platform[];
runtimeVersion?: string;
} = {}): {
inputDir: string;
platforms: Platform[];
runtimeVersion: string;
} {
/* eslint-disable node/no-sync */
vol.mkdirpSync(path.join(projectRoot, exportDir, 'bundles'));
for (const platform of platforms) {
vol.writeFileSync(
path.join(projectRoot, exportDir, 'bundles', `${platform}-fake.js`),
`console.log("fake bundle for ${platform}");`
);
}
jest.mocked(collectAssetsAsync).mockResolvedValue(
Object.fromEntries(
platforms.map(platform => [
platform,
{
assets: [],
launchAsset: {
contentType: 'application/javascript',
path: path.join(projectRoot, exportDir, 'bundles', `${platform}-fake.js`),
},
},
])
)
);
jest.mocked(uploadAssetsAsync).mockResolvedValue({
// platforms are mocked all containing only the launch asset
assetCount: platforms.length,
uniqueAssetCount: platforms.length,
uniqueUploadedAssetCount: platforms.length,
assetLimitPerUpdateGroup: 9001,
});
jest.mocked(Updates.getRuntimeVersion).mockReturnValue(runtimeVersion);
return { inputDir: exportDir, platforms, runtimeVersion };
}
@@ -0,0 +1,344 @@
import { AppJSONConfig, PackageJSONConfig, getConfig } from '@expo/config';
import { vol } from 'memfs';
import { instance, mock } from 'ts-mockito';
import LoggedInContextField from '../../../commandUtils/context/LoggedInContextField';
import ProjectConfigContextField from '../../../commandUtils/context/ProjectConfigContextField';
import { ExpoGraphqlClient } from '../../../commandUtils/context/contextUtils/createGraphqlClient';
import FeatureGateEnvOverrides from '../../../commandUtils/gating/FeatureGateEnvOverrides';
import FeatureGating from '../../../commandUtils/gating/FeatureGating';
import { jester } from '../../../credentials/__tests__/fixtures-constants';
import { CodeSigningInfo, UpdateFragment } from '../../../graphql/generated';
import { PublishMutation } from '../../../graphql/mutations/PublishMutation';
import { AppQuery } from '../../../graphql/queries/AppQuery';
import { UpdateQuery } from '../../../graphql/queries/UpdateQuery';
import { getBranchNameFromChannelNameAsync } from '../../../update/getBranchNameFromChannelNameAsync';
import { selectUpdateGroupOnBranchAsync } from '../../../update/queries';
import UpdateRepublish from '../republish';
const projectRoot = '/test-project';
const commandOptions = { root: projectRoot } as any;
const updateStub: UpdateFragment = {
id: 'update-1234',
group: 'group-1234',
branch: { id: 'branch-1234', name: 'main' },
message: 'test message',
runtimeVersion: 'exposdk:47.0.0',
platform: 'ios',
gitCommitHash: 'commit',
manifestFragment: JSON.stringify({ fake: 'manifest' }),
manifestPermalink: 'https://expo.dev/fake/manifest/link',
codeSigningInfo: null,
createdAt: '2022-01-01T12:00:00Z',
};
const codeSigningStub: CodeSigningInfo = {
keyid: 'keyid',
alg: 'alg',
sig: 'sig',
};
jest.mock('fs');
jest.mock('@expo/config');
jest.mock('../../../commandUtils/context/contextUtils/getProjectIdAsync');
jest.mock('../../../graphql/mutations/PublishMutation');
jest.mock('../../../graphql/queries/AppQuery');
jest.mock('../../../graphql/queries/UpdateQuery');
jest.mock('../../../update/getBranchNameFromChannelNameAsync');
jest.mock('../../../update/queries');
jest.mock('../../../ora', () => ({
ora: () => ({
start: () => ({ succeed: () => {}, fail: () => {} }),
}),
}));
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'];
mockTestProject();
await expect(new UpdateRepublish(flags, commandOptions).run()).rejects.toThrow(
/--branch=main cannot also be provided when using --group/
);
});
it('errors when providing both --channel and --branch', async () => {
const flags = ['--channel=main', '--branch=main'];
mockTestProject();
await expect(new UpdateRepublish(flags, commandOptions).run()).rejects.toThrow(
/--branch=main cannot also be provided when using --channel/
);
});
it('errors when providing both --group and --channel', async () => {
const flags = ['--group=1234', '--channel=main'];
mockTestProject();
await expect(new UpdateRepublish(flags, commandOptions).run()).rejects.toThrow(
/--channel=main cannot also be provided when using --group/
);
});
it('errors when update group is empty', async () => {
const flags = ['--group=1234'];
mockTestProject();
jest.mocked(UpdateQuery.viewUpdateGroupAsync).mockResolvedValue([]);
await expect(new UpdateRepublish(flags, commandOptions).run()).rejects.toThrow(
'There are no published updates found'
);
});
it('errors when update group has no update for requested platform', async () => {
const flags = ['--group=1234', '--platform=android'];
mockTestProject();
jest.mocked(UpdateQuery.viewUpdateGroupAsync).mockResolvedValue([
{
...updateStub,
platform: 'ios',
},
]);
await expect(new UpdateRepublish(flags, commandOptions).run()).rejects.toThrow(
'There are no updates on branch "main" published for the platform(s) "android" with group ID "1234". Did you mean to publish a new update instead?'
);
});
it('re-creates update with --group and --message', async () => {
const flags = ['--group=1234', '--message=test-republish'];
mockTestProject();
// Mock queries to retrieve the update and code signing info
jest.mocked(UpdateQuery.viewUpdateGroupAsync).mockResolvedValue([updateStub]);
// Mock mutations to store the new update
jest.mocked(PublishMutation.publishUpdateGroupAsync).mockResolvedValue([
{
...updateStub,
id: 'update-new',
platform: 'ios',
manifestPermalink: 'https://expo.dev/@test/test-project/manifest',
},
]);
await new UpdateRepublish(flags, commandOptions).run();
expect(PublishMutation.publishUpdateGroupAsync).toHaveBeenCalledWith(
expect.any(Object), // graphql client
expect.arrayContaining([
expect.objectContaining({
branchId: updateStub.branch.id,
runtimeVersion: updateStub.runtimeVersion,
updateInfoGroup: expect.objectContaining({
ios: expect.any(Object),
}),
gitCommitHash: updateStub.gitCommitHash,
awaitingCodeSigningInfo: false,
}),
])
);
expect(PublishMutation.setCodeSigningInfoAsync).not.toHaveBeenCalled();
});
it('re-creates update using codesigning with --group and --message', async () => {
const flags = ['--group=1234', '--message=test-republish'];
const codeSigning = {
alg: 'alg',
keyid: 'keyid',
sig: 'sig',
};
mockTestProject();
// Mock queries to retrieve the update and code signing info
jest
.mocked(UpdateQuery.viewUpdateGroupAsync)
.mockResolvedValue([{ ...updateStub, codeSigningInfo: codeSigningStub }]);
// Mock mutations to store the new update
jest.mocked(PublishMutation.publishUpdateGroupAsync).mockResolvedValue([
{
...updateStub,
id: 'update-new',
platform: 'ios',
manifestPermalink: 'https://expo.dev/@test/test-project/manifest',
},
]);
jest.mocked(PublishMutation.setCodeSigningInfoAsync).mockResolvedValue({} as any);
await new UpdateRepublish(flags, commandOptions).run();
expect(PublishMutation.publishUpdateGroupAsync).toHaveBeenCalledWith(
expect.any(Object), // graphql client
expect.arrayContaining([
expect.objectContaining({
branchId: updateStub.branch.id,
runtimeVersion: updateStub.runtimeVersion,
updateInfoGroup: expect.objectContaining({
ios: expect.any(Object),
}),
gitCommitHash: updateStub.gitCommitHash,
awaitingCodeSigningInfo: true,
}),
])
);
expect(PublishMutation.setCodeSigningInfoAsync).toHaveBeenCalledWith(
expect.any(Object), // graphql client
'update-new',
expect.objectContaining(codeSigning)
);
});
it('re-creates update with --branch and --message', async () => {
const flags = ['--branch=branch123', '--message=test-republish'];
mockTestProject();
// Mock the prompt to ask the user which update to republish, from branch
jest.mocked(selectUpdateGroupOnBranchAsync).mockResolvedValue([updateStub]);
// Mock mutations to store the new update
jest.mocked(PublishMutation.publishUpdateGroupAsync).mockResolvedValue([
{
...updateStub,
id: 'update-new',
platform: 'ios',
manifestPermalink: 'https://expo.dev/@test/test-project/manifest',
},
]);
await new UpdateRepublish(flags, commandOptions).run();
expect(selectUpdateGroupOnBranchAsync).toHaveBeenCalledWith(
expect.any(Object), // graphql client
expect.objectContaining({ branchName: 'branch123' })
);
expect(PublishMutation.publishUpdateGroupAsync).toHaveBeenCalledWith(
expect.any(Object), // graphql client
expect.arrayContaining([
expect.objectContaining({
branchId: updateStub.branch.id,
runtimeVersion: updateStub.runtimeVersion,
updateInfoGroup: expect.objectContaining({
ios: expect.any(Object),
}),
gitCommitHash: updateStub.gitCommitHash,
awaitingCodeSigningInfo: false,
}),
])
);
});
it('re-creates update with --channel and --message', async () => {
const flags = ['--channel=channel123', '--message=test-republish'];
mockTestProject();
// Mock resolving the channel to branch name, only valid for a single branch connected
jest.mocked(getBranchNameFromChannelNameAsync).mockResolvedValue('branchFromChannel');
// Mock the prompt to ask the user which update to republish, from branch
jest.mocked(selectUpdateGroupOnBranchAsync).mockResolvedValue([updateStub]);
// Mock mutations to store the new update
jest.mocked(PublishMutation.publishUpdateGroupAsync).mockResolvedValue([
{
...updateStub,
id: 'update-new',
platform: 'ios',
manifestPermalink: 'https://expo.dev/@test/test-project/manifest',
},
]);
await new UpdateRepublish(flags, commandOptions).run();
expect(selectUpdateGroupOnBranchAsync).toHaveBeenCalledWith(
expect.any(Object), // graphql client
expect.objectContaining({ branchName: 'branchFromChannel' })
);
expect(PublishMutation.publishUpdateGroupAsync).toHaveBeenCalledWith(
expect.any(Object), // graphql client
expect.arrayContaining([
expect.objectContaining({
branchId: updateStub.branch.id,
runtimeVersion: updateStub.runtimeVersion,
updateInfoGroup: expect.objectContaining({
ios: expect.any(Object),
}),
gitCommitHash: updateStub.gitCommitHash,
awaitingCodeSigningInfo: false,
}),
])
);
});
});
/** Create a new in-memory project, based on src/commands/project/__tests__/init.test.ts */
function mockTestProject({
configuredProjectId = '1234',
}: {
configuredProjectId?: string;
} = {}): void {
const packageJSON: PackageJSONConfig = {
name: 'testing123',
version: '0.1.0',
description: 'fake description',
main: 'index.js',
};
const appJSON: AppJSONConfig = {
expo: {
name: 'testing 123',
version: '0.1.0',
slug: 'testing-123',
sdkVersion: '33.0.0',
owner: jester.accounts[0].name,
extra: {
eas: {
projectId: configuredProjectId,
},
},
},
};
vol.fromJSON(
{
'package.json': JSON.stringify(packageJSON),
'app.json': JSON.stringify(appJSON),
},
projectRoot
);
const mockManifest = { exp: appJSON.expo };
const graphqlClient = instance(mock<ExpoGraphqlClient>({}));
jest.mocked(getConfig).mockReturnValue(mockManifest as any);
jest.spyOn(ProjectConfigContextField.prototype, 'getValueAsync').mockResolvedValue({
exp: mockManifest.exp,
projectDir: projectRoot,
projectId: configuredProjectId,
});
jest.spyOn(LoggedInContextField.prototype, 'getValueAsync').mockResolvedValue({
actor: jester,
featureGating: new FeatureGating({}, new FeatureGateEnvOverrides()),
graphqlClient,
});
jest.mocked(AppQuery.byIdAsync).mockResolvedValue({
id: '1234',
slug: 'testing-123',
fullName: '@jester/testing-123',
ownerAccount: jester.accounts[0],
});
}
@@ -1,10 +1,14 @@
import { Flags } from '@oclif/core';
import chalk from 'chalk';
import EasCommand from '../../commandUtils/EasCommand';
import { EASNonInteractiveFlag } from '../../commandUtils/flags';
import Log from '../../log';
import { RequestedPlatform } from '../../platform';
import { ensureEASUpdatesIsConfiguredAsync } from '../../update/configure';
import {
ensureEASUpdateIsConfiguredAsync,
ensureEASUpdateIsConfiguredInEasJsonAsync,
} from '../../update/configure';
export default class UpdateConfigure extends EasCommand {
static override description = 'configure the project to support EAS Update';
@@ -38,14 +42,33 @@ export default class UpdateConfigure extends EasCommand {
'💡 The following process will configure your project to run EAS Update. These changes only apply to your local project files and you can safely revert them at any time.'
);
await ensureEASUpdatesIsConfiguredAsync(graphqlClient, {
await ensureEASUpdateIsConfiguredAsync(graphqlClient, {
exp,
projectId,
projectDir,
platform,
});
await ensureEASUpdateIsConfiguredInEasJsonAsync(projectDir);
Log.addNewLineIfNone();
Log.log(`🎉 Your app is configured to run EAS Update!`);
Log.log(`🎉 Your app is configured with EAS Update!`);
Log.newLine();
Log.log(`${chalk.bold('Next steps')}:`);
Log.newLine();
Log.log('Update a production build:');
Log.log(`1. Create a new build. Example: ${chalk.bold('eas build --profile production')}.`);
Log.log('2. Make changes in your project.');
Log.log(`3. Publish an update. Example: ${chalk.bold('eas update --channel production')}.`);
Log.log('4. Force close and reopen the app at least twice to view the update.');
Log.newLine();
Log.log('Preview an update:');
Log.log(
`1. Publish an update to a branch. Example: ${chalk.bold('eas update --branch new-feature')}.`
);
Log.log(
'2. In Expo Go or a development build, navigate to Projects > [project name] > Branch > Open.'
);
}
}
+117 -180
View File
@@ -17,12 +17,10 @@ import fetch from '../../fetch';
import {
PublishUpdateGroupInput,
StatuspageServiceName,
Update,
UpdateInfoGroup,
UpdatePublishMutation,
} from '../../graphql/generated';
import { PublishMutation } from '../../graphql/mutations/PublishMutation';
import { UpdateQuery } from '../../graphql/queries/UpdateQuery';
import Log, { learnMore, link } from '../../log';
import { ora } from '../../ora';
import { RequestedPlatform, requestedPlatformDisplayNames } from '../../platform';
@@ -39,9 +37,13 @@ import {
} from '../../project/publish';
import { resolveWorkflowAsync } from '../../project/workflow';
import { promptAsync } from '../../prompts';
import { ensureEASUpdatesIsConfiguredAsync } from '../../update/configure';
import { selectUpdateGroupOnBranchAsync } from '../../update/queries';
import { formatUpdateMessage, truncateString as truncateUpdateMessage } from '../../update/utils';
import { ensureEASUpdateIsConfiguredAsync } from '../../update/configure';
import { getBranchNameFromChannelNameAsync } from '../../update/getBranchNameFromChannelNameAsync';
import {
formatUpdateMessage,
getUpdateGroupJsonInfo,
truncateString as truncateUpdateMessage,
} from '../../update/utils';
import {
checkManifestBodyAgainstUpdateInfoGroup,
getCodeSigningInfoAsync,
@@ -59,24 +61,26 @@ export const defaultPublishPlatforms: Partial<PublishPlatform>[] = ['android', '
type RawUpdateFlags = {
auto: boolean;
branch?: string;
channel?: string;
message?: string;
group?: string;
republish?: boolean;
platform: string;
'input-dir': string;
'skip-bundler': boolean;
'private-key-path'?: string;
'non-interactive': boolean;
json: boolean;
/** @deprecated see UpdateRepublish command */
group?: string;
/** @deprecated see UpdateRepublish command */
republish?: boolean;
};
type UpdateFlags = {
auto: boolean;
platform: ExpoCLIExportPlatformFlag;
branchName?: string;
channelName?: string;
updateMessage?: string;
republish: boolean;
groupId?: string;
inputDir: string;
skipBundler: boolean;
privateKeyPath?: string;
@@ -107,16 +111,20 @@ export default class UpdatePublish extends EasCommand {
description: 'Branch to publish the update group on',
required: false,
}),
channel: Flags.string({
description: 'Channel that the published update should affect',
required: false,
}),
message: Flags.string({
description: 'A short message describing the update',
required: false,
}),
republish: Flags.boolean({
description: 'Republish an update group',
description: 'Republish an update group (deprecated, see republish command)',
exclusive: ['input-dir', 'skip-bundler'],
}),
group: Flags.string({
description: 'Update group to republish',
description: 'Update group to republish (deprecated, see republish command)',
exclusive: ['input-dir', 'skip-bundler'],
}),
'input-dir': Flags.string({
@@ -161,16 +169,15 @@ export default class UpdatePublish extends EasCommand {
let {
auto: autoFlag,
platform: platformFlag,
branchName,
channelName,
updateMessage,
republish,
groupId,
inputDir,
skipBundler,
privateKeyPath,
json: jsonFlag,
nonInteractive,
} = this.sanitizeFlags(rawFlags);
let branchName = this.sanitizeFlags(rawFlags).branchName;
const {
getDynamicProjectConfigAsync,
@@ -197,7 +204,7 @@ export default class UpdatePublish extends EasCommand {
await maybeWarnAboutEasOutagesAsync(graphqlClient, [StatuspageServiceName.EasUpdate]);
await ensureEASUpdatesIsConfiguredAsync(graphqlClient, {
await ensureEASUpdateIsConfiguredAsync(graphqlClient, {
exp: expPossiblyWithoutEasUpdateConfigured,
platform: getRequestedPlatform(platformFlag),
projectDir,
@@ -209,22 +216,31 @@ export default class UpdatePublish extends EasCommand {
let realizedPlatforms: PublishPlatform[] = [];
if (channelName && branchName) {
throw new Error(
'Cannot specify both --channel and --branch. Specify either --channel, --branch, or --auto'
);
}
if (channelName) {
branchName = await getBranchNameFromChannelNameAsync(graphqlClient, projectId, channelName);
}
if (!branchName) {
if (autoFlag) {
branchName = await getDefaultBranchNameAsync();
} else if (nonInteractive) {
throw new Error('Must supply --branch or use --auto when in non-interactive mode');
throw new Error('Must supply --channel, --branch or --auto when in non-interactive mode');
} else {
try {
const branch = await selectBranchOnAppAsync(graphqlClient, {
projectId,
promptTitle: `Which branch would you like to ${
republish ? 'republish' : 'publish'
} on?`,
displayTextForListItem: updateBranch =>
`${updateBranch.name} ${chalk.grey(
promptTitle: `Which branch would you like to publish on?`,
displayTextForListItem: updateBranch => ({
title: `${updateBranch.name} ${chalk.grey(
`- current update: ${formatUpdateMessage(updateBranch.updates[0])}`
)}`,
}),
paginatedQueryOptions,
});
branchName = branch.name;
@@ -243,156 +259,72 @@ export default class UpdatePublish extends EasCommand {
}
}
if (!updateMessage && autoFlag) {
updateMessage = (await getVcsClient().getLastCommitMessageAsync())?.trim();
}
if (!updateMessage) {
if (nonInteractive) {
throw new Error('Must supply --message or use --auto when in non-interactive mode');
}
const validationMessage = 'publish message may not be empty.';
if (jsonFlag) {
throw new Error(validationMessage);
}
({ updateMessage } = await promptAsync({
type: 'text',
name: 'updateMessage',
message: `Provide an update message.`,
initial: (await getVcsClient().getLastCommitMessageAsync())?.trim(),
validate: (value: any) => (value ? true : validationMessage),
}));
}
// build bundle and upload assets for a new publish
if (!skipBundler) {
const bundleSpinner = ora().start('Exporting...');
try {
await buildBundlesAsync({ projectDir, inputDir, exp, platformFlag });
bundleSpinner.succeed('Exported bundle(s)');
} catch (e) {
bundleSpinner.fail('Export failed');
throw e;
}
}
// After possibly bundling, assert that the input directory can be found.
const distRoot = await resolveInputDirectoryAsync(inputDir, { skipBundler });
const assetSpinner = ora().start('Uploading...');
let unsortedUpdateInfoGroups: UpdateInfoGroup = {};
let oldMessage: string, oldRuntimeVersion: string;
let uploadedAssetCount = 0;
let assetLimitPerUpdateGroup = 0;
if (republish) {
// If we are republishing, we don't need to worry about building the bundle or uploading the assets.
// Instead we get the `updateInfoGroup` from the update we wish to republish.
let updatesToRepublish: Pick<
Update,
'group' | 'message' | 'runtimeVersion' | 'manifestFragment' | 'platform'
>[];
if (groupId) {
const updatesByGroup = await UpdateQuery.viewUpdateGroupAsync(graphqlClient, {
groupId,
});
updatesToRepublish = updatesByGroup;
} else {
if (nonInteractive) {
throw new Error('Must supply --group when in non-interactive mode');
try {
const collectedAssets = await collectAssetsAsync(distRoot);
const assets = filterExportedPlatformsByFlag(collectedAssets, platformFlag);
realizedPlatforms = Object.keys(assets) as PublishPlatform[];
const uploadResults = await uploadAssetsAsync(
graphqlClient,
assets,
projectId,
(totalAssets, missingAssets) => {
assetSpinner.text = `Uploading (${totalAssets - missingAssets}/${totalAssets})`;
}
updatesToRepublish = await selectUpdateGroupOnBranchAsync(graphqlClient, {
projectId,
branchName,
paginatedQueryOptions,
});
}
const updatesToRepublishFilteredByPlatform = updatesToRepublish.filter(
// Only republish to the specified platforms
update => platformFlag === 'all' || update.platform === platformFlag
);
if (updatesToRepublishFilteredByPlatform.length === 0) {
throw new Error(
`There are no updates on branch "${branchName}" published for the platform(s) "${platformFlag}" with group ID "${
groupId ? groupId : updatesToRepublish[0].group
}". Did you mean to publish a new update instead?`
);
}
let publicationPlatformMessage: string;
if (platformFlag === 'all') {
if (updatesToRepublishFilteredByPlatform.length < defaultPublishPlatforms.length) {
Log.warn(`You are republishing an update that wasn't published for all platforms.`);
}
publicationPlatformMessage = `The republished update will appear on the same platforms it was originally published on: ${updatesToRepublishFilteredByPlatform
.map(update => update.platform)
.join(', ')}`;
} else {
publicationPlatformMessage = `The republished update will appear only on: ${platformFlag}`;
}
Log.withTick(publicationPlatformMessage);
for (const update of updatesToRepublishFilteredByPlatform) {
const { manifestFragment } = update;
const platform = update.platform as PublishPlatform;
unsortedUpdateInfoGroups[platform] = JSON.parse(manifestFragment);
}
realizedPlatforms = updatesToRepublishFilteredByPlatform.map(
update => update.platform as PublishPlatform
);
// These are the same for each member of an update group
groupId = updatesToRepublishFilteredByPlatform[0].group;
oldMessage = updatesToRepublishFilteredByPlatform[0].message ?? '';
oldRuntimeVersion = updatesToRepublishFilteredByPlatform[0].runtimeVersion;
if (!updateMessage) {
if (nonInteractive) {
throw new Error('Must supply --message when in non-interactive mode');
}
const validationMessage = 'publish message may not be empty.';
if (jsonFlag) {
throw new Error(validationMessage);
}
({ updateMessage } = await promptAsync({
type: 'text',
name: 'updateMessage',
message: `Provide an update message.`,
initial: `Republish "${oldMessage!}" - group: ${groupId}`,
validate: (value: any) => (value ? true : validationMessage),
}));
}
} else {
if (!updateMessage && autoFlag) {
updateMessage = (await getVcsClient().getLastCommitMessageAsync())?.trim();
}
if (!updateMessage) {
if (nonInteractive) {
throw new Error('Must supply --message or use --auto when in non-interactive mode');
}
const validationMessage = 'publish message may not be empty.';
if (jsonFlag) {
throw new Error(validationMessage);
}
({ updateMessage } = await promptAsync({
type: 'text',
name: 'updateMessage',
message: `Provide an update message.`,
initial: (await getVcsClient().getLastCommitMessageAsync())?.trim(),
validate: (value: any) => (value ? true : validationMessage),
}));
}
// build bundle and upload assets for a new publish
if (!skipBundler) {
const bundleSpinner = ora().start('Exporting...');
try {
await buildBundlesAsync({ projectDir, inputDir, exp, platformFlag });
bundleSpinner.succeed('Exported bundle(s)');
} catch (e) {
bundleSpinner.fail('Export failed');
throw e;
}
}
// After possibly bundling, assert that the input directory can be found.
const distRoot = await resolveInputDirectoryAsync(inputDir, { skipBundler });
const assetSpinner = ora().start('Uploading...');
try {
const collectedAssets = await collectAssetsAsync(distRoot);
const assets = filterExportedPlatformsByFlag(collectedAssets, platformFlag);
realizedPlatforms = Object.keys(assets) as PublishPlatform[];
const uploadResults = await uploadAssetsAsync(
graphqlClient,
assets,
projectId,
(totalAssets, missingAssets) => {
assetSpinner.text = `Uploading (${totalAssets - missingAssets}/${totalAssets})`;
}
);
uploadedAssetCount = uploadResults.uniqueUploadedAssetCount;
assetLimitPerUpdateGroup = uploadResults.assetLimitPerUpdateGroup;
unsortedUpdateInfoGroups = await buildUnsortedUpdateInfoGroupAsync(assets, exp);
const uploadAssetSuccessMessage = uploadedAssetCount
? `Uploaded ${uploadedAssetCount} ${uploadedAssetCount === 1 ? 'platform' : 'platforms'}`
: `Uploaded: No changes detected`;
assetSpinner.succeed(uploadAssetSuccessMessage);
} catch (e) {
assetSpinner.fail('Failed to upload');
throw e;
}
uploadedAssetCount = uploadResults.uniqueUploadedAssetCount;
assetLimitPerUpdateGroup = uploadResults.assetLimitPerUpdateGroup;
unsortedUpdateInfoGroups = await buildUnsortedUpdateInfoGroupAsync(assets, exp);
const uploadAssetSuccessMessage = uploadedAssetCount
? `Uploaded ${uploadedAssetCount} ${uploadedAssetCount === 1 ? 'platform' : 'platforms'}`
: `Uploaded: No changes detected`;
assetSpinner.succeed(uploadAssetSuccessMessage);
} catch (e) {
assetSpinner.fail('Failed to upload');
throw e;
}
const truncatedMessage = truncateUpdateMessage(updateMessage!, 1024);
@@ -441,15 +373,10 @@ export default class UpdatePublish extends EasCommand {
])
);
if (republish && !oldRuntimeVersion) {
throw new Error(
'Cannot find the runtime version of the update group that is being republished.'
);
}
return {
branchId,
updateInfoGroup: localUpdateInfoGroup,
runtimeVersion: republish ? oldRuntimeVersion : runtimeVersion,
runtimeVersion,
message: truncatedMessage,
gitCommitHash,
isGitWorkingTreeDirty,
@@ -511,7 +438,7 @@ export default class UpdatePublish extends EasCommand {
}
if (jsonFlag) {
printJsonOnlyOutput(newUpdates);
printJsonOnlyOutput(getUpdateGroupJsonInfo(newUpdates));
} else {
if (new Set(newUpdates.map(update => update.group)).size > 1) {
Log.addNewLineIfNone();
@@ -585,26 +512,36 @@ export default class UpdatePublish extends EasCommand {
private sanitizeFlags(flags: RawUpdateFlags): UpdateFlags {
const nonInteractive = flags['non-interactive'] ?? false;
const { auto, branch: branchName, message: updateMessage } = flags;
if (nonInteractive && !auto && !(branchName && updateMessage)) {
const { auto, branch: branchName, channel: channelName, message: updateMessage } = flags;
if (nonInteractive && !auto && !(updateMessage && (branchName || channelName))) {
Errors.error(
'--auto or both --branch and --message are required when updating in non-interactive mode',
'--branch and --message, or --channel and --message are required when updating in non-interactive mode unless --auto is specified',
{ exit: 1 }
);
}
const groupId = flags.group;
const republish = flags.republish || !!groupId; // When --group is defined, we are republishing
if (nonInteractive && republish && !groupId) {
Errors.error(`--group is required when updating in non-interactive mode`, { exit: 1 });
if (flags.group || flags.republish) {
// Pick the first flag set that is defined, in this specific order
const args = [
['--group', flags.group],
['--branch', flags.branch],
].filter(([_, value]) => value)[0];
Log.newLine();
Log.warn(
'The --group and --republish flags are deprecated, use the republish command instead:'
);
Log.warn(` ${chalk.bold([`eas update:republish`, ...(args ?? [])].join(' '))}`);
Log.newLine();
Errors.error('--group and --republish flags are deprecated', { exit: 1 });
}
return {
auto,
branchName,
channelName,
updateMessage,
groupId,
republish,
inputDir: flags['input-dir'],
skipBundler: flags['skip-bundler'],
platform: flags.platform as RequestedPlatform,
+3 -1
View File
@@ -70,7 +70,9 @@ export default class UpdateList extends EasCommand {
const selectedBranch = await selectBranchOnAppAsync(graphqlClient, {
projectId,
promptTitle: 'Which branch would you like to view?',
displayTextForListItem: updateBranch => updateBranch.name,
displayTextForListItem: updateBranch => ({
title: updateBranch.name,
}),
paginatedQueryOptions:
// discard limit and offset because this query is not those flag's intended target
{
@@ -0,0 +1,377 @@
import { Platform } from '@expo/config';
import { Flags } from '@oclif/core';
import { getUpdateGroupUrl } from '../../build/utils/url';
import EasCommand from '../../commandUtils/EasCommand';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
import { getPaginatedQueryOptions } from '../../commandUtils/pagination';
import { Update } from '../../graphql/generated';
import { PublishMutation } from '../../graphql/mutations/PublishMutation';
import { UpdateQuery } from '../../graphql/queries/UpdateQuery';
import Log, { link } from '../../log';
import { ora } from '../../ora';
import { getOwnerAccountForProjectIdAsync } from '../../project/projectUtils';
import { promptAsync } from '../../prompts';
import { getBranchNameFromChannelNameAsync } from '../../update/getBranchNameFromChannelNameAsync';
import { selectUpdateGroupOnBranchAsync } from '../../update/queries';
import { truncateString as truncateUpdateMessage } from '../../update/utils';
import formatFields from '../../utils/formatFields';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
const defaultRepublishPlatforms: Platform[] = ['android', 'ios'];
type UpdateRepublishRawFlags = {
branch?: string;
channel?: string;
group?: string;
message?: string;
platform: string;
'non-interactive': boolean;
json?: boolean;
};
type UpdateRepublishFlags = {
branchName?: string;
channelName?: string;
groupId?: string;
updateMessage?: string;
platform: Platform[];
nonInteractive: boolean;
json: boolean;
};
type UpdateToRepublish = {
groupId: string;
branchId: string;
branchName: string;
} & Pick<
Update,
| 'message'
| 'runtimeVersion'
| 'manifestFragment'
| 'platform'
| 'gitCommitHash'
| 'codeSigningInfo'
>;
export default class UpdateRepublish extends EasCommand {
static override description = 'rollback to an existing update';
static override flags = {
channel: Flags.string({
description: 'Channel name to select an update to republish from',
exclusive: ['branch', 'group'],
}),
branch: Flags.string({
description: 'Branch name to select an update to republish from',
exclusive: ['channel', 'group'],
}),
group: Flags.string({
description: 'Update group ID to republish',
exclusive: ['branch', 'channel'],
}),
message: Flags.string({
description: 'Short message describing the republished update',
required: false,
}),
platform: Flags.enum({
char: 'p',
options: [...defaultRepublishPlatforms, 'all'],
default: 'all',
required: false,
}),
...EasNonInteractiveAndJsonFlags,
};
static override contextDefinition = {
...this.ContextOptions.ProjectConfig,
...this.ContextOptions.LoggedIn,
};
async runAsync(): Promise<void> {
const { flags: rawFlags } = await this.parse(UpdateRepublish);
const flags = this.sanitizeFlags(rawFlags);
const {
projectConfig: { exp, projectId },
loggedIn: { graphqlClient },
} = await this.getContextAsync(UpdateRepublish, {
nonInteractive: flags.nonInteractive,
});
if (flags.json) {
enableJsonOutput();
}
const existingUpdates = await getOrAskUpdatesAsync(graphqlClient, projectId, flags);
const updatesToPublish = existingUpdates.filter(update =>
flags.platform.includes(update.platform as Platform)
);
if (existingUpdates.length === 0) {
throw new Error(`There are no published updates found`);
}
if (updatesToPublish.length === 0) {
throw new Error(
`There are no updates on branch "${
existingUpdates[0].branchName
}" published for the platform(s) "${rawFlags.platform}" with group ID "${
flags.groupId ? flags.groupId : updatesToPublish[0].groupId
}". Did you mean to publish a new update instead?`
);
}
if (rawFlags.platform === 'all') {
Log.withTick(`The republished update will appear only on: ${rawFlags.platform}`);
} else {
const platformsFromUpdates = updatesToPublish.map(update => update.platform);
if (platformsFromUpdates.length < defaultRepublishPlatforms.length) {
Log.warn(`You are republishing an update that wasn't published for all platforms.`);
}
Log.withTick(
`The republished update will appear on the same platforms it was originally published on: ${platformsFromUpdates.join(
', '
)}`
);
}
// This command only republishes a single update group
// The update group properties are the same for all updates
const { branchId, branchName, runtimeVersion } = updatesToPublish[0];
const updateMessage = await getOrAskUpdateMessageAsync(updatesToPublish, flags);
// If codesigning was created for the original update, we need to add it to the republish
const shouldRepublishWithCodesigning = updatesToPublish.some(update => update.codeSigningInfo);
if (shouldRepublishWithCodesigning) {
Log.withTick(
`The republished update will be signed with the same codesigning as the original update.`
);
}
const publishIndicator = ora('Republishing...').start();
let updatesRepublished: Awaited<ReturnType<typeof PublishMutation.publishUpdateGroupAsync>>;
try {
updatesRepublished = await PublishMutation.publishUpdateGroupAsync(graphqlClient, [
{
branchId,
runtimeVersion,
message: updateMessage,
updateInfoGroup: Object.fromEntries(
updatesToPublish.map(update => [update.platform, JSON.parse(update.manifestFragment)])
),
gitCommitHash: updatesToPublish[0].gitCommitHash,
awaitingCodeSigningInfo: shouldRepublishWithCodesigning,
},
]);
if (shouldRepublishWithCodesigning) {
const codeSigningByPlatform = Object.fromEntries(
updatesToPublish.map(update => [update.platform, update.codeSigningInfo])
);
await Promise.all(
updatesRepublished.map(async update => {
const codeSigning = codeSigningByPlatform[update.platform];
if (codeSigning) {
await PublishMutation.setCodeSigningInfoAsync(graphqlClient, update.id, codeSigning);
}
})
);
}
publishIndicator.succeed('Republished update');
} catch (error: any) {
publishIndicator.fail('Failed to republish update');
throw error;
}
if (flags.json) {
return printJsonOnlyOutput(updatesRepublished);
}
const updatesRepublishedByPlatform = Object.fromEntries(
updatesRepublished.map(update => [update.platform, update])
);
const updateGroupUrl = getUpdateGroupUrl(
(await getOwnerAccountForProjectIdAsync(graphqlClient, projectId)).name,
exp.slug,
updatesRepublished[0].group
);
Log.addNewLineIfNone();
Log.log(
formatFields([
{ label: 'Branch', value: branchName },
{ label: 'Runtime version', value: updatesRepublished[0].runtimeVersion },
{ label: 'Platform', value: updatesRepublished.map(update => update.platform).join(', ') },
{ label: 'Update Group ID', value: updatesRepublished[0].id },
...(updatesRepublishedByPlatform.android
? [{ label: 'Android update ID', value: updatesRepublishedByPlatform.android.id }]
: []),
...(updatesRepublishedByPlatform.ios
? [{ label: 'iOS update ID', value: updatesRepublishedByPlatform.ios.id }]
: []),
{ label: 'Message', value: updateMessage },
{ label: 'Website link', value: link(updateGroupUrl, { dim: false }) },
])
);
}
sanitizeFlags(rawFlags: UpdateRepublishRawFlags): UpdateRepublishFlags {
const branchName = rawFlags.branch;
const channelName = rawFlags.channel;
const groupId = rawFlags.group;
const nonInteractive = rawFlags['non-interactive'];
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[]);
return {
branchName,
channelName,
groupId,
platform,
updateMessage: rawFlags.message,
json: rawFlags.json ?? false,
nonInteractive,
};
}
}
/** Retrieve the update group from either the update group id, or select from branch name. */
async function getOrAskUpdatesAsync(
graphqlClient: ExpoGraphqlClient,
projectId: string,
flags: UpdateRepublishFlags
): Promise<UpdateToRepublish[]> {
if (flags.groupId) {
const updateGroups = await UpdateQuery.viewUpdateGroupAsync(graphqlClient, {
groupId: flags.groupId,
});
return updateGroups.map(group => ({
...group,
groupId: group.group,
branchId: group.branch.id,
branchName: group.branch.name,
}));
}
if (flags.branchName) {
return await askUpdatesFromBranchNameAsync(graphqlClient, {
...flags,
branchName: flags.branchName,
projectId,
});
}
if (flags.channelName) {
return await askUpdatesFromChannelNameAsync(graphqlClient, {
...flags,
channelName: flags.channelName,
projectId,
});
}
throw new Error('--channel, --branch, or --group is required');
}
/** Ask the user which update needs to be republished by branch name, this requires interactive mode */
async function askUpdatesFromBranchNameAsync(
graphqlClient: ExpoGraphqlClient,
{
projectId,
branchName,
json,
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 updateGroups = await selectUpdateGroupOnBranchAsync(graphqlClient, {
projectId,
branchName,
paginatedQueryOptions: getPaginatedQueryOptions({ json, 'non-interactive': nonInteractive }),
});
return updateGroups.map(group => ({
...group,
groupId: group.id,
branchId: group.branch.id,
branchName: group.branch.name,
}));
}
/** Ask the user which update needs to be republished by channel name, this requires interactive mode */
async function askUpdatesFromChannelNameAsync(
graphqlClient: ExpoGraphqlClient,
{
projectId,
channelName,
json,
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, {
projectId,
branchName,
json,
nonInteractive,
});
}
/** Get or ask the user for the update (group) message for the republish */
async function getOrAskUpdateMessageAsync(
updates: UpdateToRepublish[],
flags: UpdateRepublishFlags
): Promise<string> {
if (flags.updateMessage) {
return sanitizeUpdateMessage(flags.updateMessage);
}
if (flags.nonInteractive || flags.json) {
throw new Error('Must supply --message when in non-interactive mode');
}
// This command only uses a single update group to republish, meaning these values are always identical
const oldGroupId = updates[0].groupId;
const oldUpdateMessage = updates[0].message;
const { updateMessage } = await promptAsync({
type: 'text',
name: 'updateMessage',
message: 'Provide an update message.',
initial: `Republish "${oldUpdateMessage!}" - group: ${oldGroupId}`,
validate: (value: any) => (value ? true : 'Update message may not be empty.'),
});
return sanitizeUpdateMessage(updateMessage);
}
function sanitizeUpdateMessage(updateMessage: string): string {
if (updateMessage !== truncateUpdateMessage(updateMessage, 1024)) {
Log.warn('Update message exceeds the allowed 1024 character limit, truncated update message.');
return truncateUpdateMessage(updateMessage, 1024);
}
return updateMessage;
}
+8 -3
View File
@@ -4,7 +4,11 @@ import EasCommand from '../../commandUtils/EasCommand';
import { EasJsonOnlyFlag } from '../../commandUtils/flags';
import { UpdateQuery } from '../../graphql/queries/UpdateQuery';
import Log from '../../log';
import { formatUpdateGroup, getUpdateGroupDescriptions } from '../../update/utils';
import {
formatUpdateGroup,
getUpdateGroupDescriptions,
getUpdateGroupJsonInfo,
} from '../../update/utils';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
export default class UpdateView extends EasCommand {
@@ -41,11 +45,12 @@ export default class UpdateView extends EasCommand {
}
const updatesByGroup = await UpdateQuery.viewUpdateGroupAsync(graphqlClient, { groupId });
const [updateGroupDescription] = getUpdateGroupDescriptions([updatesByGroup]);
if (jsonFlag) {
printJsonOnlyOutput(updateGroupDescription);
printJsonOnlyOutput(getUpdateGroupJsonInfo(updatesByGroup));
} else {
const [updateGroupDescription] = getUpdateGroupDescriptions([updatesByGroup]);
Log.log(chalk.bold('Update group:'));
Log.log(formatUpdateGroup(updateGroupDescription));
+17 -5
View File
@@ -2,11 +2,13 @@ import { Flags } from '@oclif/core';
import chalk from 'chalk';
import EasCommand from '../../commandUtils/EasCommand';
import { EasJsonOnlyFlag } from '../../commandUtils/flags';
import { WebhookType } from '../../graphql/generated';
import { WebhookQuery } from '../../graphql/queries/WebhookQuery';
import Log from '../../log';
import { ora } from '../../ora';
import { getDisplayNameForProjectIdAsync } from '../../project/projectUtils';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
import { formatWebhook } from '../../webhooks/formatWebhook';
export default class WebhookList extends EasCommand {
@@ -17,6 +19,7 @@ export default class WebhookList extends EasCommand {
description: 'Event type that triggers the webhook',
options: [WebhookType.Build, WebhookType.Submit],
}),
...EasJsonOnlyFlag,
};
static override contextDefinition = {
@@ -26,8 +29,12 @@ export default class WebhookList extends EasCommand {
async runAsync(): Promise<void> {
const {
flags: { event },
flags: { event, json },
} = await this.parse(WebhookList);
if (json) {
enableJsonOutput();
}
const {
projectConfig: { projectId },
loggedIn: { graphqlClient },
@@ -48,10 +55,15 @@ export default class WebhookList extends EasCommand {
spinner.fail(`There are no webhooks on project ${projectDisplayName}`);
} else {
spinner.succeed(`Found ${webhooks.length} webhooks on project ${projectDisplayName}`);
const list = webhooks
.map(webhook => formatWebhook(webhook))
.join(`\n\n${chalk.dim('———')}\n\n`);
Log.log(`\n${list}`);
if (json) {
printJsonOnlyOutput(webhooks);
} else {
const list = webhooks
.map(webhook => formatWebhook(webhook))
.join(`\n\n${chalk.dim('———')}\n\n`);
Log.log(`\n${list}`);
}
}
} catch (err) {
spinner.fail(
@@ -1,9 +1,10 @@
import chalk from 'chalk';
import terminalLink from 'terminal-link';
// @ts-ignore
import TurndownService from 'turndown';
import wrapAnsi from 'wrap-ansi';
import { link } from '../../../log';
const turndownServices: Record<string, any> = {};
function getService(rootUrl: string): TurndownService {
@@ -44,10 +45,7 @@ function getService(rootUrl: string): TurndownService {
if (href.startsWith('/')) {
href = `${rootUrl}${href}`;
}
if (terminalLink.isSupported) {
return chalk.cyan(terminalLink(content, href));
}
return `${chalk.cyan(content)} (${chalk.underline(href)})`;
return chalk.cyan(link(href, { text: content }));
},
});
+6 -3
View File
@@ -44,10 +44,11 @@ export async function selectAppleTeamOnAccountAsync(
}),
promptOptions: {
title: selectionPromptTitle,
createDisplayTextForSelectionPromptListItem: appleTeam =>
appleTeam.appleTeamName
makePartialChoiceObject: appleTeam => ({
title: appleTeam.appleTeamName
? `${appleTeam.appleTeamName} (ID: ${appleTeam.appleTeamIdentifier})`
: appleTeam.appleTeamIdentifier,
}),
getIdentifierForQueryItem: appleTeam => appleTeam.id,
},
});
@@ -87,7 +88,9 @@ export async function selectAppleDeviceOnAppleTeamAsync(
}),
promptOptions: {
title: selectionPromptTitle,
createDisplayTextForSelectionPromptListItem: appleDevice => formatDeviceLabel(appleDevice),
makePartialChoiceObject: appleDevice => ({
title: formatDeviceLabel(appleDevice),
}),
getIdentifierForQueryItem: appleTeam => appleTeam.id,
},
});
+363 -78
View File
@@ -370,6 +370,13 @@ export type AccountMutationSetPushSecurityEnabledArgs = {
pushSecurityEnabled: Scalars['Boolean'];
};
export type AccountNotificationSubscriptionInput = {
accountId: Scalars['ID'];
event: NotificationEvent;
type: NotificationType;
userId: Scalars['ID'];
};
export type AccountQuery = {
__typename?: 'AccountQuery';
/** Query an Account by ID */
@@ -398,9 +405,8 @@ export type AccountSsoConfiguration = {
clientSecret: Scalars['String'];
createdAt: Scalars['DateTime'];
id: Scalars['ID'];
issuer?: Maybe<Scalars['String']>;
issuer: Scalars['String'];
jwksEndpoint?: Maybe<Scalars['String']>;
redirectUri: Scalars['String'];
revokeEndpoint?: Maybe<Scalars['String']>;
tokenEndpoint?: Maybe<Scalars['String']>;
updatedAt: Scalars['DateTime'];
@@ -413,9 +419,8 @@ export type AccountSsoConfigurationData = {
authProviderIdentifier: Scalars['String'];
clientIdentifier: Scalars['String'];
clientSecret: Scalars['String'];
issuer?: InputMaybe<Scalars['String']>;
issuer: Scalars['String'];
jwksEndpoint?: InputMaybe<Scalars['String']>;
redirectUri: Scalars['String'];
revokeEndpoint?: InputMaybe<Scalars['String']>;
tokenEndpoint?: InputMaybe<Scalars['String']>;
userInfoEndpoint?: InputMaybe<Scalars['String']>;
@@ -456,9 +461,8 @@ export type AccountSsoConfigurationPublicData = {
authProviderIdentifier: Scalars['String'];
clientIdentifier: Scalars['String'];
id: Scalars['ID'];
issuer?: Maybe<Scalars['String']>;
issuer: Scalars['String'];
jwksEndpoint?: Maybe<Scalars['String']>;
redirectUri: Scalars['String'];
revokeEndpoint?: Maybe<Scalars['String']>;
tokenEndpoint?: Maybe<Scalars['String']>;
userInfoEndpoint?: Maybe<Scalars['String']>;
@@ -787,6 +791,7 @@ export type AndroidJobInput = {
developmentClient?: InputMaybe<Scalars['Boolean']>;
experimental?: InputMaybe<Scalars['JSONObject']>;
gradleCommand?: InputMaybe<Scalars['String']>;
mode?: InputMaybe<BuildMode>;
projectArchive: ProjectArchiveSourceInput;
projectRootDirectory: Scalars['String'];
releaseChannel?: InputMaybe<Scalars['String']>;
@@ -815,6 +820,7 @@ export type AndroidJobOverridesInput = {
developmentClient?: InputMaybe<Scalars['Boolean']>;
experimental?: InputMaybe<Scalars['JSONObject']>;
gradleCommand?: InputMaybe<Scalars['String']>;
mode?: InputMaybe<BuildMode>;
releaseChannel?: InputMaybe<Scalars['String']>;
secrets?: InputMaybe<AndroidJobSecretsInput>;
updates?: InputMaybe<BuildUpdatesInput>;
@@ -922,8 +928,10 @@ export type App = Project & {
/** Classic update release channel names that have at least one build */
buildsReleaseChannels: Array<Scalars['String']>;
deployment?: Maybe<Deployment>;
deploymentNew?: Maybe<DeploymentNew>;
/** Deployments associated with this app */
deployments: Array<Deployment>;
deploymentsNew: DeploymentsConnection;
description: Scalars['String'];
/** Environment secrets for an app */
environmentSecrets: Array<EnvironmentSecret>;
@@ -1051,6 +1059,13 @@ export type AppDeploymentArgs = {
};
/** Represents an Exponent App (or Experience in legacy terms) */
export type AppDeploymentNewArgs = {
channel: Scalars['String'];
runtimeVersion: Scalars['String'];
};
/** Represents an Exponent App (or Experience in legacy terms) */
export type AppDeploymentsArgs = {
limit: Scalars['Int'];
@@ -1059,6 +1074,15 @@ export type AppDeploymentsArgs = {
};
/** Represents an Exponent App (or Experience in legacy terms) */
export type AppDeploymentsNewArgs = {
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 AppEnvironmentSecretsArgs = {
filterNames?: InputMaybe<Array<Scalars['String']>>;
@@ -1206,6 +1230,13 @@ export type AppMutationSetPushSecurityEnabledArgs = {
pushSecurityEnabled: Scalars['Boolean'];
};
export type AppNotificationSubscriptionInput = {
appId: Scalars['ID'];
event: NotificationEvent;
type: NotificationType;
userId: Scalars['ID'];
};
export enum AppPlatform {
Android = 'ANDROID',
Ios = 'IOS'
@@ -1739,6 +1770,7 @@ export type BillingPeriod = {
__typename?: 'BillingPeriod';
anchor: Scalars['DateTime'];
end: Scalars['DateTime'];
id: Scalars['ID'];
start: Scalars['DateTime'];
};
@@ -1752,6 +1784,7 @@ export type Build = ActivityTimelineProjectActivity & BuildOrBuildJob & {
appBuildVersion?: Maybe<Scalars['String']>;
appVersion?: Maybe<Scalars['String']>;
artifacts?: Maybe<BuildArtifacts>;
buildMode?: Maybe<BuildMode>;
buildProfile?: Maybe<Scalars['String']>;
canRetry: Scalars['Boolean'];
cancelingActor?: Maybe<Actor>;
@@ -1800,6 +1833,12 @@ export type Build = ActivityTimelineProjectActivity & BuildOrBuildJob & {
workerStartedAt?: Maybe<Scalars['DateTime']>;
};
/** Represents an EAS Build */
export type BuildCanRetryArgs = {
newMode?: InputMaybe<BuildMode>;
};
export type BuildArtifact = {
__typename?: 'BuildArtifact';
manifestPlistUrl?: Maybe<Scalars['String']>;
@@ -1932,6 +1971,7 @@ export type BuildMetadataInput = {
appIdentifier?: InputMaybe<Scalars['String']>;
appName?: InputMaybe<Scalars['String']>;
appVersion?: InputMaybe<Scalars['String']>;
buildMode?: InputMaybe<BuildMode>;
buildProfile?: InputMaybe<Scalars['String']>;
channel?: InputMaybe<Scalars['String']>;
cliVersion?: InputMaybe<Scalars['String']>;
@@ -1960,6 +2000,11 @@ export type BuildMetrics = {
buildWaitTime?: Maybe<Scalars['Int']>;
};
export enum BuildMode {
Build = 'BUILD',
Resign = 'RESIGN'
}
export type BuildMutation = {
__typename?: 'BuildMutation';
/**
@@ -2116,13 +2161,21 @@ export type BuildQueryByIdArgs = {
buildId: Scalars['ID'];
};
export type BuildResignInput = {
applicationArchiveSource?: InputMaybe<ProjectArchiveSourceInput>;
};
export enum BuildResourceClass {
AndroidDefault = 'ANDROID_DEFAULT',
AndroidLarge = 'ANDROID_LARGE',
AndroidMedium = 'ANDROID_MEDIUM',
IosDefault = 'IOS_DEFAULT',
IosIntelLarge = 'IOS_INTEL_LARGE',
IosIntelMedium = 'IOS_INTEL_MEDIUM',
IosLarge = 'IOS_LARGE',
/** @experimental This resource class is not yet ready to be used in production. For testing purposes only. */
IosM1Large = 'IOS_M1_LARGE',
IosM1Medium = 'IOS_M1_MEDIUM',
IosMedium = 'IOS_MEDIUM',
Legacy = 'LEGACY'
}
@@ -2141,7 +2194,8 @@ export type BuildUpdatesInput = {
export enum BuildWorkflow {
Generic = 'GENERIC',
Managed = 'MANAGED'
Managed = 'MANAGED',
Unknown = 'UNKNOWN'
}
export enum CacheControlScope {
@@ -2381,11 +2435,55 @@ export type Deployment = {
runtimeVersion: Scalars['String'];
};
export type DeploymentBuildEdge = {
__typename?: 'DeploymentBuildEdge';
cursor: Scalars['String'];
node: Build;
};
/** Represents the connection over the builds edge of a Deployment */
export type DeploymentBuildsConnection = {
__typename?: 'DeploymentBuildsConnection';
edges: Array<DeploymentBuildEdge>;
pageInfo: PageInfo;
};
export type DeploymentEdge = {
__typename?: 'DeploymentEdge';
cursor: Scalars['String'];
node: DeploymentNew;
};
/** Represents a Deployment - a set of Builds with the same Runtime Version and Channel */
export type DeploymentNew = {
__typename?: 'DeploymentNew';
builds: DeploymentBuildsConnection;
channel: UpdateChannel;
id: Scalars['ID'];
runtime: Runtime;
};
/** Represents a Deployment - a set of Builds with the same Runtime Version and Channel */
export type DeploymentNewBuildsArgs = {
after?: InputMaybe<Scalars['String']>;
before?: InputMaybe<Scalars['String']>;
first?: InputMaybe<Scalars['Int']>;
last?: InputMaybe<Scalars['Int']>;
};
export type DeploymentOptions = {
/** Max number of associated builds to return */
buildListMaxSize?: InputMaybe<Scalars['Int']>;
};
/** Represents the connection over the deploymentsNew edge of an App */
export type DeploymentsConnection = {
__typename?: 'DeploymentsConnection';
edges: Array<DeploymentEdge>;
pageInfo: PageInfo;
};
export enum DistributionType {
Internal = 'INTERNAL',
Simulator = 'SIMULATOR',
@@ -2414,6 +2512,21 @@ export enum EasServiceMetric {
UniqueUsers = 'UNIQUE_USERS'
}
export type EasTotalPlanEnablement = {
__typename?: 'EASTotalPlanEnablement';
total: Scalars['Int'];
unit?: Maybe<EasTotalPlanEnablementUnit>;
};
export enum EasTotalPlanEnablementUnit {
Build = 'BUILD',
Byte = 'BYTE',
Concurrency = 'CONCURRENCY',
Request = 'REQUEST',
Updater = 'UPDATER',
User = 'USER'
}
export type EditUpdateBranchInput = {
appId?: InputMaybe<Scalars['ID']>;
id?: InputMaybe<Scalars['ID']>;
@@ -2547,7 +2660,7 @@ export type GitHubAppInstallationAccessibleRepositoriesArgs = {
export type GitHubAppInstallationAccessibleRepository = {
__typename?: 'GitHubAppInstallationAccessibleRepository';
defaultBranch: Scalars['String'];
defaultBranch?: Maybe<Scalars['String']>;
description?: Maybe<Scalars['String']>;
id: Scalars['Int'];
name: Scalars['String'];
@@ -2982,6 +3095,7 @@ export type IosJobInput = {
/** @deprecated */
distribution?: InputMaybe<DistributionType>;
experimental?: InputMaybe<Scalars['JSONObject']>;
mode?: InputMaybe<BuildMode>;
projectArchive: ProjectArchiveSourceInput;
projectRootDirectory: Scalars['String'];
releaseChannel?: InputMaybe<Scalars['String']>;
@@ -3008,10 +3122,13 @@ export type IosJobOverridesInput = {
/** @deprecated */
distribution?: InputMaybe<DistributionType>;
experimental?: InputMaybe<Scalars['JSONObject']>;
mode?: InputMaybe<BuildMode>;
releaseChannel?: InputMaybe<Scalars['String']>;
resign?: InputMaybe<BuildResignInput>;
scheme?: InputMaybe<Scalars['String']>;
secrets?: InputMaybe<IosJobSecretsInput>;
simulator?: InputMaybe<Scalars['Boolean']>;
type?: InputMaybe<BuildWorkflow>;
updates?: InputMaybe<BuildUpdatesInput>;
username?: InputMaybe<Scalars['String']>;
version?: InputMaybe<IosJobVersionInput>;
@@ -3214,9 +3331,59 @@ export type MeMutationUpdateProfileArgs = {
export type MeteredBillingStatus = {
__typename?: 'MeteredBillingStatus';
EAS_BUILD: Scalars['Boolean'];
EAS_UPDATE: Scalars['Boolean'];
};
export enum NotificationEvent {
BuildComplete = 'BUILD_COMPLETE',
SubmissionComplete = 'SUBMISSION_COMPLETE'
}
export type NotificationSubscription = {
__typename?: 'NotificationSubscription';
account?: Maybe<Account>;
actor?: Maybe<Actor>;
app?: Maybe<App>;
createdAt: Scalars['DateTime'];
event: NotificationEvent;
id: Scalars['ID'];
type: NotificationType;
};
export type NotificationSubscriptionFilter = {
accountId?: InputMaybe<Scalars['ID']>;
appId?: InputMaybe<Scalars['ID']>;
event?: InputMaybe<NotificationEvent>;
type?: InputMaybe<NotificationType>;
};
export type NotificationSubscriptionMutation = {
__typename?: 'NotificationSubscriptionMutation';
subscribeToEventForAccount: SubscribeToNotificationResult;
subscribeToEventForApp: SubscribeToNotificationResult;
unsubscribe: UnsubscribeFromNotificationResult;
};
export type NotificationSubscriptionMutationSubscribeToEventForAccountArgs = {
input: AccountNotificationSubscriptionInput;
};
export type NotificationSubscriptionMutationSubscribeToEventForAppArgs = {
input: AppNotificationSubscriptionInput;
};
export type NotificationSubscriptionMutationUnsubscribeArgs = {
id: Scalars['ID'];
};
export enum NotificationType {
Email = 'EMAIL'
}
export type Offer = {
__typename?: 'Offer';
features?: Maybe<Array<Maybe<Feature>>>;
@@ -3249,6 +3416,14 @@ export enum Order {
Desc = 'DESC'
}
export type PageInfo = {
__typename?: 'PageInfo';
endCursor?: Maybe<Scalars['String']>;
hasNextPage: Scalars['Boolean'];
hasPreviousPage: Scalars['Boolean'];
startCursor?: Maybe<Scalars['String']>;
};
export type PartialManifest = {
assets: Array<InputMaybe<PartialManifestAsset>>;
extra?: InputMaybe<Scalars['JSONObject']>;
@@ -3277,6 +3452,8 @@ export enum Permission {
View = 'VIEW'
}
export type PlanEnablement = Concurrencies | EasTotalPlanEnablement;
export type Project = {
description: Scalars['String'];
fullName: Scalars['String'];
@@ -3298,6 +3475,7 @@ export type ProjectArchiveSourceInput = {
export enum ProjectArchiveSourceType {
Gcs = 'GCS',
None = 'NONE',
S3 = 'S3',
Url = 'URL'
}
@@ -3492,6 +3670,8 @@ export type RootMutation = {
keystoreGenerationUrl: KeystoreGenerationUrlMutation;
/** Mutations that modify the currently authenticated User */
me: MeMutation;
/** Mutations that modify a NotificationSubscription */
notificationSubscription: NotificationSubscriptionMutation;
/** Mutations that create, update, and delete Robots */
robot: RobotMutation;
serverlessFunction: ServerlessFunctionMutation;
@@ -3582,6 +3762,8 @@ export type RootQuery = {
meActor?: Maybe<Actor>;
project: ProjectQuery;
snack: SnackQuery;
/** Top-level query object for querying SSO Users. */
ssoUser: SsoUserQuery;
/** Top-level query object for querying Expo status page services. */
statuspageService: StatuspageServiceQuery;
submissions: SubmissionQuery;
@@ -3632,6 +3814,97 @@ export type RootQueryUserByUsernameArgs = {
username: Scalars['String'];
};
export type Runtime = {
__typename?: 'Runtime';
app: App;
firstBuildCreatedAt: Scalars['DateTime'];
id: Scalars['ID'];
version: Scalars['String'];
};
/** Represents a human SSO (not robot) actor. */
export type SsoUser = Actor & {
__typename?: 'SSOUser';
/** Access Tokens belonging to this actor, none at present */
accessTokens: Array<AccessToken>;
accounts: Array<Account>;
/** Coalesced project activity for all apps belonging to all accounts this user belongs to. Only resolves for the viewer. */
activityTimelineProjectActivities: Array<ActivityTimelineProjectActivity>;
appCount: Scalars['Int'];
appetizeCode?: Maybe<Scalars['String']>;
/** Apps this user has published. If this user is the viewer, this field returns the apps the user has access to. */
apps: Array<App>;
created: Scalars['DateTime'];
displayName: Scalars['String'];
/**
* Server feature gate values for this actor, optionally filtering by desired gates.
* Only resolves for the viewer.
*/
featureGates: Scalars['JSONObject'];
firstName?: Maybe<Scalars['String']>;
fullName?: Maybe<Scalars['String']>;
githubUsername?: Maybe<Scalars['String']>;
id: Scalars['ID'];
industry?: Maybe<Scalars['String']>;
isExpoAdmin: Scalars['Boolean'];
lastName?: Maybe<Scalars['String']>;
location?: Maybe<Scalars['String']>;
/** Associated accounts */
primaryAccount: Account;
profilePhoto: Scalars['String'];
/** Snacks associated with this account */
snacks: Array<Snack>;
twitterUsername?: Maybe<Scalars['String']>;
username: Scalars['String'];
};
/** Represents a human SSO (not robot) actor. */
export type SsoUserActivityTimelineProjectActivitiesArgs = {
createdBefore?: InputMaybe<Scalars['DateTime']>;
filterTypes?: InputMaybe<Array<ActivityTimelineProjectActivityType>>;
limit: Scalars['Int'];
};
/** Represents a human SSO (not robot) actor. */
export type SsoUserAppsArgs = {
includeUnpublished?: InputMaybe<Scalars['Boolean']>;
limit: Scalars['Int'];
offset: Scalars['Int'];
};
/** Represents a human SSO (not robot) actor. */
export type SsoUserFeatureGatesArgs = {
filter?: InputMaybe<Array<Scalars['String']>>;
};
/** Represents a human SSO (not robot) actor. */
export type SsoUserSnacksArgs = {
limit: Scalars['Int'];
offset: Scalars['Int'];
};
export type SsoUserQuery = {
__typename?: 'SSOUserQuery';
/** Query an SSOUser by ID */
byId: SsoUser;
/** Query an SSOUser by username */
byUsername: SsoUser;
};
export type SsoUserQueryByIdArgs = {
userId: Scalars['ID'];
};
export type SsoUserQueryByUsernameArgs = {
username: Scalars['String'];
};
export type SecondFactorBooleanResult = {
__typename?: 'SecondFactorBooleanResult';
success: Scalars['Boolean'];
@@ -3977,6 +4250,11 @@ export enum SubmissionStatus {
InQueue = 'IN_QUEUE'
}
export type SubscribeToNotificationResult = {
__typename?: 'SubscribeToNotificationResult';
notificationSubscription: NotificationSubscription;
};
export type SubscriptionDetails = {
__typename?: 'SubscriptionDetails';
addons: Array<AddonDetails>;
@@ -3990,6 +4268,7 @@ export type SubscriptionDetails = {
meteredBillingStatus: MeteredBillingStatus;
name?: Maybe<Scalars['String']>;
nextInvoice?: Maybe<Scalars['DateTime']>;
planEnablement?: Maybe<PlanEnablement>;
planId?: Maybe<Scalars['String']>;
price: Scalars['Int'];
status?: Maybe<Scalars['String']>;
@@ -3997,6 +4276,16 @@ export type SubscriptionDetails = {
willCancel?: Maybe<Scalars['Boolean']>;
};
export type SubscriptionDetailsPlanEnablementArgs = {
serviceMetric: EasServiceMetric;
};
export type UnsubscribeFromNotificationResult = {
__typename?: 'UnsubscribeFromNotificationResult';
notificationSubscription: NotificationSubscription;
};
export type Update = ActivityTimelineProjectActivity & {
__typename?: 'Update';
activityTimestamp: Scalars['DateTime'];
@@ -4244,22 +4533,11 @@ export type User = Actor & {
hasPendingUserInvitations: Scalars['Boolean'];
id: Scalars['ID'];
industry?: Maybe<Scalars['String']>;
/** @deprecated No longer supported */
isEmailUnsubscribed: Scalars['Boolean'];
isExpoAdmin: Scalars['Boolean'];
/** @deprecated No longer supported */
isLegacy?: Maybe<Scalars['Boolean']>;
/** @deprecated No longer supported */
isOnboarded?: Maybe<Scalars['Boolean']>;
isSecondFactorAuthenticationEnabled: Scalars['Boolean'];
/** @deprecated No longer supported */
lastLogin?: Maybe<Scalars['DateTime']>;
lastName?: Maybe<Scalars['String']>;
/** @deprecated No longer supported */
lastPasswordReset?: Maybe<Scalars['DateTime']>;
/** @deprecated 'likes' have been deprecated. */
likes?: Maybe<Array<Maybe<App>>>;
location?: Maybe<Scalars['String']>;
notificationSubscriptions: Array<NotificationSubscription>;
/** Pending UserInvitations for this user. Only resolves for the viewer. */
pendingUserInvitations: Array<UserInvitation>;
/** Associated accounts */
@@ -4271,8 +4549,6 @@ export type User = Actor & {
snacks: Array<Snack>;
twitterUsername?: Maybe<Scalars['String']>;
username: Scalars['String'];
/** @deprecated No longer supported */
wasLegacy?: Maybe<Scalars['Boolean']>;
};
@@ -4299,9 +4575,8 @@ export type UserFeatureGatesArgs = {
/** Represents a human (not robot) actor. */
export type UserLikesArgs = {
limit: Scalars['Int'];
offset: Scalars['Int'];
export type UserNotificationSubscriptionsArgs = {
filter?: InputMaybe<NotificationSubscriptionFilter>;
};
@@ -4319,26 +4594,26 @@ export type UserDataInput = {
githubUsername?: InputMaybe<Scalars['String']>;
id?: InputMaybe<Scalars['ID']>;
industry?: InputMaybe<Scalars['String']>;
isEmailUnsubscribed?: InputMaybe<Scalars['Boolean']>;
isLegacy?: InputMaybe<Scalars['Boolean']>;
isOnboarded?: InputMaybe<Scalars['Boolean']>;
lastName?: InputMaybe<Scalars['String']>;
location?: InputMaybe<Scalars['String']>;
profilePhoto?: InputMaybe<Scalars['String']>;
twitterUsername?: InputMaybe<Scalars['String']>;
username?: InputMaybe<Scalars['String']>;
wasLegacy?: InputMaybe<Scalars['Boolean']>;
};
/** An pending invitation sent to an email granting membership on an Account. */
export type UserInvitation = {
__typename?: 'UserInvitation';
accountName: Scalars['String'];
/** If the invite is for a personal team, the profile photo of account owner */
accountProfilePhoto?: Maybe<Scalars['String']>;
created: Scalars['DateTime'];
/** Email to which this invitation was sent */
email: Scalars['String'];
expires: Scalars['DateTime'];
id: Scalars['ID'];
/** If the invite is for an organization or a personal team */
isForOrganization: Scalars['Boolean'];
/** Account permissions to be granted upon acceptance of this invitation */
permissions: Array<Permission>;
/** Role to be granted upon acceptance of this invitation */
@@ -4407,11 +4682,13 @@ export type UserInvitationMutationResendUserInvitationArgs = {
export type UserInvitationPublicData = {
__typename?: 'UserInvitationPublicData';
accountName: Scalars['String'];
accountProfilePhoto?: Maybe<Scalars['String']>;
created: Scalars['DateTime'];
email: Scalars['String'];
expires: Scalars['DateTime'];
/** Email to which this invitation was sent */
id: Scalars['ID'];
isForOrganization: Scalars['Boolean'];
};
export type UserInvitationPublicDataQuery = {
@@ -4444,7 +4721,7 @@ export type UserQuery = {
export type UserQueryByIdArgs = {
userId: Scalars['String'];
userId: Scalars['ID'];
};
@@ -4646,7 +4923,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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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'];
@@ -4654,7 +4931,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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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'];
@@ -4662,7 +4939,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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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;
@@ -4716,7 +4993,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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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'];
@@ -4777,7 +5054,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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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'];
@@ -4816,7 +5093,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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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'];
@@ -4831,7 +5108,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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } } } };
export type CreateIosAppBuildCredentialsMutationVariables = Exact<{
iosAppBuildCredentialsInput: IosAppBuildCredentialsInput;
@@ -4839,7 +5116,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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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 SetDistributionCertificateMutationVariables = Exact<{
iosAppBuildCredentialsId: Scalars['ID'];
@@ -4847,7 +5124,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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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 SetProvisioningProfileMutationVariables = Exact<{
iosAppBuildCredentialsId: Scalars['ID'];
@@ -4855,7 +5132,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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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 CreateIosAppCredentialsMutationVariables = Exact<{
iosAppCredentialsInput: IosAppCredentialsInput;
@@ -4864,7 +5141,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 | null, actor: { __typename?: 'Robot', 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 | null, actor: { __typename?: 'Robot', 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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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 | null, 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 | null, 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'];
@@ -4872,7 +5149,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 | null, actor: { __typename?: 'Robot', 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 | null, actor: { __typename?: 'Robot', 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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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 | null, 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 | null, 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'];
@@ -4880,7 +5157,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 | null, actor: { __typename?: 'Robot', 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 | null, actor: { __typename?: 'Robot', 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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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 | null, 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 | null, 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'];
@@ -4930,14 +5207,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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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'];
@@ -4953,7 +5230,7 @@ export type ApplePushKeyByAccountQueryVariables = Exact<{
}>;
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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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'];
@@ -4979,7 +5256,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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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 IosAppCredentialsWithBuildCredentialsByAppIdentifierIdQueryVariables = Exact<{
projectFullName: Scalars['String'];
@@ -4988,7 +5265,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 | null, actor: { __typename?: 'Robot', 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 | null, actor: { __typename?: 'Robot', 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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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 | null, 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 | null, 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'];
@@ -4996,7 +5273,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 | null, actor: { __typename?: 'Robot', 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 | null, actor: { __typename?: 'Robot', 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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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 | null, 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 | null, 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;
@@ -5020,7 +5297,7 @@ export type CreateAndroidBuildMutationVariables = Exact<{
}>;
export type CreateAndroidBuildMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', createAndroidBuild: { __typename?: 'CreateBuildResult', build: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, 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: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } }, deprecationInfo?: { __typename?: 'EASBuildDeprecationInfo', type: EasBuildDeprecationInfoType, message: string } | null } } };
export type CreateAndroidBuildMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', createAndroidBuild: { __typename?: 'CreateBuildResult', build: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, completedAt?: any | null, resourceClass: BuildResourceClass, 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 } }, deprecationInfo?: { __typename?: 'EASBuildDeprecationInfo', type: EasBuildDeprecationInfoType, message: string } | null } } };
export type CreateIosBuildMutationVariables = Exact<{
appId: Scalars['ID'];
@@ -5030,7 +5307,15 @@ export type CreateIosBuildMutationVariables = Exact<{
}>;
export type CreateIosBuildMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', createIosBuild: { __typename?: 'CreateBuildResult', build: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, 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: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } }, deprecationInfo?: { __typename?: 'EASBuildDeprecationInfo', type: EasBuildDeprecationInfoType, message: string } | null } } };
export type CreateIosBuildMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', createIosBuild: { __typename?: 'CreateBuildResult', build: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, completedAt?: any | null, resourceClass: BuildResourceClass, 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 } }, deprecationInfo?: { __typename?: 'EASBuildDeprecationInfo', type: EasBuildDeprecationInfoType, message: string } | null } } };
export type RetryIosBuildMutationVariables = Exact<{
buildId: Scalars['ID'];
jobOverrides: IosJobOverridesInput;
}>;
export type RetryIosBuildMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', retryIosBuild: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, completedAt?: any | null, resourceClass: BuildResourceClass, 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 } } } };
export type CreateEnvironmentSecretForAccountMutationVariables = Exact<{
input: CreateEnvironmentSecretInput;
@@ -5072,7 +5357,7 @@ export type UpdatePublishMutationVariables = Exact<{
}>;
export type UpdatePublishMutation = { __typename?: 'RootMutation', updateBranch: { __typename?: 'UpdateBranchMutation', publishUpdateGroups: Array<{ __typename?: 'Update', id: string, group: string, runtimeVersion: string, platform: string, manifestPermalink: string }> } };
export type UpdatePublishMutation = { __typename?: 'RootMutation', updateBranch: { __typename?: 'UpdateBranchMutation', publishUpdateGroups: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, manifestPermalink: string, gitCommitHash?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', 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 SetCodeSigningInfoMutationVariables = Exact<{
updateId: Scalars['ID'];
@@ -5137,14 +5422,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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } } } };
export type LatestAppVersionQueryVariables = Exact<{
appId: Scalars['String'];
@@ -5170,7 +5455,7 @@ export type BranchesByAppQueryVariables = Exact<{
}>;
export type BranchesByAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updates: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string } }> }> } } };
export type BranchesByAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updates: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, manifestPermalink: string, gitCommitHash?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', 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 ViewBranchesOnUpdateChannelQueryVariables = Exact<{
appId: Scalars['String'];
@@ -5180,21 +5465,21 @@ export type ViewBranchesOnUpdateChannelQueryVariables = Exact<{
}>;
export type ViewBranchesOnUpdateChannelQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateChannelByName?: { __typename?: 'UpdateChannel', id: 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, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string } }>> }> } | null } } };
export type ViewBranchesOnUpdateChannelQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateChannelByName?: { __typename?: 'UpdateChannel', id: 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, manifestPermalink: string, gitCommitHash?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', 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 BuildsByIdQueryVariables = Exact<{
buildId: Scalars['ID'];
}>;
export type BuildsByIdQuery = { __typename?: 'RootQuery', builds: { __typename?: 'BuildQuery', byId: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, 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: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } } } };
export type BuildsByIdQuery = { __typename?: 'RootQuery', builds: { __typename?: 'BuildQuery', byId: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, completedAt?: any | null, resourceClass: BuildResourceClass, 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 } } } };
export type BuildsWithSubmissionsByIdQueryVariables = Exact<{
buildId: Scalars['ID'];
}>;
export type BuildsWithSubmissionsByIdQuery = { __typename?: 'RootQuery', builds: { __typename?: 'BuildQuery', byId: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, submissions: Array<{ __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logsUrl?: string | null, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null }>, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } } } };
export type BuildsWithSubmissionsByIdQuery = { __typename?: 'RootQuery', builds: { __typename?: 'BuildQuery', byId: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, completedAt?: any | null, resourceClass: BuildResourceClass, submissions: Array<{ __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logsUrl?: string | null, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null }>, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } } } };
export type ViewBuildsOnAppQueryVariables = Exact<{
appId: Scalars['String'];
@@ -5204,7 +5489,7 @@ export type ViewBuildsOnAppQueryVariables = Exact<{
}>;
export type ViewBuildsOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, builds: Array<{ __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, 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: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } }> } } };
export type ViewBuildsOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, builds: Array<{ __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, completedAt?: any | null, resourceClass: BuildResourceClass, 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 } }> } } };
export type ViewUpdateChannelOnAppQueryVariables = Exact<{
appId: Scalars['String'];
@@ -5212,7 +5497,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, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string } }>> }> } | null } } };
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, manifestPermalink: string, gitCommitHash?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', 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'];
@@ -5221,7 +5506,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, 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, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string } }>> }> }> } } };
export type ViewUpdateChannelsOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateChannels: Array<{ __typename?: 'UpdateChannel', id: string, name: string, 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, manifestPermalink: string, gitCommitHash?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', 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 EnvironmentSecretsByAppIdQueryVariables = Exact<{
appId: Scalars['String'];
@@ -5274,7 +5559,7 @@ export type ViewUpdatesByGroupQueryVariables = Exact<{
}>;
export type ViewUpdatesByGroupQuery = { __typename?: 'RootQuery', updatesByGroup: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string } }> };
export type ViewUpdatesByGroupQuery = { __typename?: 'RootQuery', updatesByGroup: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, manifestPermalink: string, gitCommitHash?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', 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 ViewUpdateGroupsOnBranchQueryVariables = Exact<{
appId: Scalars['String'];
@@ -5285,7 +5570,7 @@ export type ViewUpdateGroupsOnBranchQueryVariables = Exact<{
}>;
export type ViewUpdateGroupsOnBranchQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateBranchByName?: { __typename?: 'UpdateBranch', id: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string } }>> } | null } } };
export type ViewUpdateGroupsOnBranchQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateBranchByName?: { __typename?: 'UpdateBranch', id: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, manifestPermalink: string, gitCommitHash?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', 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 ViewUpdateGroupsOnAppQueryVariables = Exact<{
appId: Scalars['String'];
@@ -5295,12 +5580,12 @@ export type ViewUpdateGroupsOnAppQueryVariables = Exact<{
}>;
export type ViewUpdateGroupsOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string } }>> } } };
export type ViewUpdateGroupsOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, manifestPermalink: string, gitCommitHash?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', 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 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 | null, actor: { __typename?: 'Robot', 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 | null, actor: { __typename?: 'Robot', id: string } | { __typename?: 'User', id: string } }> }, accounts: Array<{ __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role?: Role | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }> } | { __typename: 'SSOUser', username: string, id: string, featureGates: any, isExpoAdmin: boolean, accounts: Array<{ __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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 | null, 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 | null, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }> } | null };
export type WebhooksByAppIdQueryVariables = Exact<{
appId: Scalars['String'];
@@ -5317,13 +5602,13 @@ 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 | null, actor: { __typename?: 'Robot', id: string } | { __typename?: 'User', id: string } }> };
export type AccountFragment = { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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 | null, actor: { __typename?: 'Robot', 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 | null, 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, 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: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } };
export type BuildFragment = { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, completedAt?: any | null, resourceClass: BuildResourceClass, 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 } };
export type BuildWithSubmissionsFragment = { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, submissions: Array<{ __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logsUrl?: string | null, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null }>, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } };
export type BuildWithSubmissionsFragment = { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, completedAt?: any | null, resourceClass: BuildResourceClass, submissions: Array<{ __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logsUrl?: string | null, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null }>, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } };
export type EnvironmentSecretFragment = { __typename?: 'EnvironmentSecret', id: string, name: string, type: EnvironmentSecretType, createdAt: any };
@@ -5331,15 +5616,15 @@ export type StatuspageServiceFragment = { __typename?: 'StatuspageService', id:
export type SubmissionFragment = { __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logsUrl?: string | null, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null };
export type UpdateFragment = { __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string } };
export type UpdateFragment = { __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, manifestPermalink: string, gitCommitHash?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', 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 UpdateBranchFragment = { __typename?: 'UpdateBranch', id: string, name: string, updates: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string } }> };
export type UpdateBranchFragment = { __typename?: 'UpdateBranch', id: string, name: string, updates: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, manifestPermalink: string, gitCommitHash?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', 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 WebhookFragment = { __typename?: 'Webhook', id: string, event: WebhookType, url: string, createdAt: any, updatedAt: any };
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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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 } };
@@ -5353,20 +5638,20 @@ export type AppleDeviceFragment = { __typename?: 'AppleDevice', id: string, iden
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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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 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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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 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 | null, actor: { __typename?: 'Robot', 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 | null, actor: { __typename?: 'Robot', 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, users: Array<{ __typename?: 'UserPermission', role?: Role | null, 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 | null, 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 | null, actor: { __typename?: 'Robot', 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 | null, actor: { __typename?: 'Robot', 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 | null, actor: { __typename?: 'Robot', 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 | null, 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 | null, 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 | null, 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 };
@@ -15,6 +15,9 @@ import {
CreateIosBuildMutationVariables,
EasBuildDeprecationInfo,
IosJobInput,
IosJobOverridesInput,
RetryIosBuildMutation,
RetryIosBuildMutationVariables,
} from '../generated';
import { BuildFragmentNode } from '../types/Build';
@@ -116,4 +119,32 @@ export const BuildMutation = {
);
return nullthrows(data.build?.createIosBuild);
},
async retryIosBuildAsync(
graphqlClient: ExpoGraphqlClient,
input: {
buildId: string;
jobOverrides: IosJobOverridesInput;
}
): Promise<BuildFragment> {
const data = await withErrorHandlingAsync(
graphqlClient
.mutation<RetryIosBuildMutation, RetryIosBuildMutationVariables>(
gql`
mutation RetryIosBuildMutation($buildId: ID!, $jobOverrides: IosJobOverridesInput!) {
build {
retryIosBuild(buildId: $buildId, jobOverrides: $jobOverrides) {
id
...BuildFragment
}
}
}
${print(BuildFragmentNode)}
`,
input,
{ noRetry: true }
)
.toPromise()
);
return nullthrows(data.build?.retryIosBuild);
},
};
@@ -1,3 +1,4 @@
import { print } from 'graphql';
import gql from 'graphql-tag';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
@@ -8,8 +9,10 @@ import {
GetSignedUploadMutationVariables,
PublishUpdateGroupInput,
SetCodeSigningInfoMutation,
UpdateFragment,
UpdatePublishMutation,
} from '../generated';
import { UpdateFragmentNode } from '../types/Update';
export const PublishMutation = {
async getUploadURLsAsync(
@@ -39,7 +42,7 @@ export const PublishMutation = {
async publishUpdateGroupAsync(
graphqlClient: ExpoGraphqlClient,
publishUpdateGroupsInput: PublishUpdateGroupInput[]
): Promise<UpdatePublishMutation['updateBranch']['publishUpdateGroups']> {
): Promise<UpdateFragment[]> {
const data = await withErrorHandlingAsync(
graphqlClient
.mutation<UpdatePublishMutation>(
@@ -48,13 +51,11 @@ export const PublishMutation = {
updateBranch {
publishUpdateGroups(publishUpdateGroupsInput: $publishUpdateGroupsInput) {
id
group
runtimeVersion
platform
manifestPermalink
...UpdateFragment
}
}
}
${print(UpdateFragmentNode)}
`,
{ publishUpdateGroupsInput }
)
@@ -1,6 +1,7 @@
import { print } from 'graphql';
import gql from 'graphql-tag';
import { ChannelNotFoundError } from '../../channel/errors';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { withErrorHandlingAsync } from '../client';
import {
@@ -59,7 +60,7 @@ export const ChannelQuery = {
const { updateChannelByName } = response.app.byId;
if (!updateChannelByName) {
throw new Error(`Could not find channel with the name ${channelName}`);
throw new ChannelNotFoundError(`Could not find channel with the name ${channelName}`);
}
return updateChannelByName;
@@ -26,6 +26,9 @@ export const UserQuery = {
... on Robot {
firstName
}
... on SSOUser {
username
}
accounts {
id
...AccountFragment
@@ -52,6 +52,8 @@ export const BuildFragmentNode = gql`
priority
createdAt
updatedAt
completedAt
resourceClass
}
`;
@@ -9,6 +9,8 @@ export const UpdateFragmentNode = gql`
runtimeVersion
platform
manifestFragment
manifestPermalink
gitCommitHash
actor {
__typename
id
@@ -23,5 +25,10 @@ export const UpdateFragmentNode = gql`
id
name
}
codeSigningInfo {
keyid
sig
alg
}
}
`;
+3 -6
View File
@@ -92,13 +92,10 @@ export function link(
url: string,
{ text = url, dim = true }: { text?: string; dim?: boolean } = {}
): string {
let output: string;
// Links can be disabled via env variables https://github.com/jamestalmage/supports-hyperlinks/blob/master/index.js
if (terminalLink.isSupported) {
output = terminalLink(text, url);
} else {
output = `${text === url ? '' : text + ': '}${chalk.underline(url)}`;
}
const output = terminalLink(text, url, {
fallback: () => (text === url ? chalk.underline(url) : `${text}: ${chalk.underline(url)}`),
});
return dim ? chalk.dim(output) : output;
}
@@ -1,11 +1,11 @@
import chalk from 'chalk';
import terminalLink from 'terminal-link';
import { getProjectDashboardUrl } from '../build/utils/url';
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
import { AppPrivacy, Role } from '../graphql/generated';
import { AppMutation } from '../graphql/mutations/AppMutation';
import { AppQuery } from '../graphql/queries/AppQuery';
import { link } from '../log';
import { ora } from '../ora';
import { confirmAsync } from '../prompts';
import { Actor } from '../user/User';
@@ -83,10 +83,7 @@ export async function fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsyn
}
const projectDashboardUrl = getProjectDashboardUrl(accountName, projectName);
const projectLink = terminalLink(projectFullName, projectDashboardUrl, {
// https://github.com/sindresorhus/terminal-link/issues/18#issuecomment-1068020361
fallback: () => `${projectFullName} (${projectDashboardUrl})`,
});
const projectLink = link(projectDashboardUrl, { text: projectFullName });
const spinner = ora(`Creating ${chalk.bold(projectFullName)} on Expo`).start();
try {
@@ -25,6 +25,8 @@ export function getUsername(exp: ExpoConfig, user: Actor): string | undefined {
}
// robot users don't have usernames
return undefined;
case 'SSOUser':
throw new Error('SSO users are not supported yet.');
}
}
+1
View File
@@ -31,6 +31,7 @@ export type RawAsset = {
contentType: string;
path: string;
};
type CollectedAssets = {
[platform in Platform]?: {
launchAsset: RawAsset;
+6 -2
View File
@@ -45,7 +45,10 @@ export async function confirmAsync(
export async function selectAsync<T>(
message: string,
choices: ExpoChoice<T>[],
options?: Options
config?: {
options?: Options;
warningMessageForDisabledEntries?: string;
}
): Promise<T> {
const { value } = await promptAsync(
{
@@ -53,8 +56,9 @@ export async function selectAsync<T>(
choices,
name: 'value',
type: 'select',
warn: config?.warningMessageForDisabledEntries,
},
options
config?.options ?? {}
);
return value ?? null;
}
+1 -1
View File
@@ -1,6 +1,6 @@
import spawnAsync, { SpawnResult } from '@expo/spawn-async';
import assert from 'assert';
import chalk from 'chalk';
import assert from 'node:assert';
import os from 'os';
import path from 'path';
+1 -1
View File
@@ -5,7 +5,7 @@ function isAab(build: BuildFragment): boolean {
}
function didArtifactsExpire(build: BuildFragment): boolean {
return new Date().getTime() - new Date(build.updatedAt).getTime() > 30 * 24 * 60 * 60 * 1000; // 30 days
return new Date().getTime() - new Date(build.completedAt).getTime() > 30 * 24 * 60 * 60 * 1000; // 30 days
}
export function isRunnableOnSimulatorOrEmulator(build: BuildFragment): boolean {
+7 -8
View File
@@ -320,23 +320,22 @@ function formatBuildChoice(build: BuildFragment, expiryDate: Date): prompts.Choi
const { id, updatedAt, runtimeVersion, buildProfile, gitCommitHash, gitCommitMessage, channel } =
build;
const formatValue = (field?: string | null): string =>
field ? chalk.bold(field) : chalk.dim('Unknown');
const formatValue = (field?: string | null): string => (field ? chalk.bold(field) : 'Unknown');
const buildDate = new Date(updatedAt);
const formattedCommitData =
gitCommitHash && gitCommitMessage
? `${chalk.dim(gitCommitHash.slice(0, 7))} "${chalk.bold(gitCommitMessage)}"`
? `${gitCommitHash.slice(0, 7)} "${chalk.bold(gitCommitMessage)}"`
: 'Unknown';
const title = `ID: ${chalk.dim(id)} (${chalk.dim(`${fromNow(buildDate)} ago`)})`;
const title = `${chalk.bold(`ID:`)} ${id} (${chalk.bold(`${fromNow(buildDate)} ago`)})`;
const description = [
`\tProfile: ${formatValue(buildProfile)}`,
`\tChannel: ${formatValue(channel)}`,
`\tRuntime version: ${formatValue(runtimeVersion)}`,
`\tCommit: ${formattedCommitData}`,
`\t${chalk.bold(`Profile:`)} ${formatValue(buildProfile)}`,
`\t${chalk.bold(`Channel:`)} ${formatValue(channel)}`,
`\t${chalk.bold(`Runtime version:`)} ${formatValue(runtimeVersion)}`,
`\t${chalk.bold(`Commit:`)} ${formattedCommitData}`,
].join('\n');
return {
+3 -4
View File
@@ -1,19 +1,18 @@
import chalk from 'chalk';
import { URL } from 'url';
import { getExpoWebsiteBaseUrl } from '../../api';
import { SubmissionFragment } from '../../graphql/generated';
import Log from '../../log';
import Log, { link } from '../../log';
import { appPlatformDisplayNames } from '../../platform';
export function printSubmissionDetailsUrls(submissions: SubmissionFragment[]): void {
if (submissions.length === 1) {
const [submission] = submissions;
Log.log(`Submission details: ${chalk.underline(getSubmissionDetailsUrl(submission))}`);
Log.log(`Submission details: ${link(getSubmissionDetailsUrl(submission))}`);
} else {
submissions.forEach(submission => {
Log.log(
`${appPlatformDisplayNames[submission.platform]} submission details: ${chalk.underline(
`${appPlatformDisplayNames[submission.platform]} submission details: ${link(
getSubmissionDetailsUrl(submission)
)}`
);
@@ -0,0 +1,155 @@
import { instance, mock } from 'ts-mockito';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { UpdateBranch, UpdateChannel } from '../../graphql/generated';
import { ChannelQuery } from '../../graphql/queries/ChannelQuery';
import { getBranchNameFromChannelNameAsync } from '../getBranchNameFromChannelNameAsync';
jest.mock('../../graphql/queries/ChannelQuery');
jest.mock('../../graphql/queries/BranchQuery');
describe(getBranchNameFromChannelNameAsync, () => {
beforeEach(() => {
jest.resetAllMocks();
});
test('returns branch name when channel exists and has one connected branch', async () => {
const graphqlClient = instance(mock<ExpoGraphqlClient>());
jest.mocked(ChannelQuery.viewUpdateChannelAsync).mockImplementationOnce(
async () =>
mockUpdateChannel({
channelName: 'test-channel-name',
branchNames: ['test-branch-name'],
}) as any
);
const result = await getBranchNameFromChannelNameAsync(
graphqlClient,
'test-project-id',
'channel-name'
);
expect(result).toBe('test-branch-name');
});
test('errors when no branch is connected to channel', async () => {
const graphqlClient = instance(mock<ExpoGraphqlClient>());
jest.mocked(ChannelQuery.viewUpdateChannelAsync).mockImplementationOnce(
async () =>
mockUpdateChannel({
channelName: 'test-channel-name',
}) as any
);
expect(
getBranchNameFromChannelNameAsync(graphqlClient, 'test-project-id', 'test-channel-name')
).rejects.toThrow(
"Channel has no branches associated with it. Run 'eas channel:edit' to map a branch"
);
});
test('errors when more than one branch is connected to channel', async () => {
const graphqlClient = instance(mock<ExpoGraphqlClient>());
jest.mocked(ChannelQuery.viewUpdateChannelAsync).mockImplementationOnce(
async () =>
mockUpdateChannel({
channelName: 'test-channel-name',
branchNames: ['test-branch-name', 'test-branch-name-2'],
}) as any
);
expect(
getBranchNameFromChannelNameAsync(graphqlClient, 'test-project-id', 'test-channel-name')
).rejects.toThrow(
"Channel has multiple branches associated with it. Instead, use '--branch' instead of '--channel'"
);
});
test('creates channel and branch when channel does not exist, and returns branch name', async () => {
const graphqlClient = instance(mock<ExpoGraphqlClient>());
jest.mocked(ChannelQuery.viewUpdateChannelAsync).mockImplementationOnce(
async () =>
mockUpdateChannel({
channelName: 'test-channel-name',
branchNames: ['test-branch-name'],
}) as any
);
const result = await getBranchNameFromChannelNameAsync(
graphqlClient,
'test-project-id',
'test-channel-name'
);
expect(result).toBe('test-branch-name');
});
});
function mockUpdateChannel({
channelName,
branchNames,
}: {
channelName?: string;
branchNames?: string[];
}): UpdateChannel {
return {
id: 'a2a1fa12-9d6a-433a-a432-49c64ef8439f',
name: channelName ?? 'default-channel-name',
createdAt: '2022-12-07T02:24:29.786Z',
appId: '123',
updatedAt: '2022-12-07T02:24:29.786Z',
branchMapping:
'{"data":[{"branchId":"f9dc4dbb-663f-4a19-8cf2-a783b484d2db","branchMappingLogic":"true"}],"version":0}',
updateBranches: branchNames ? mockUpdateBranches(branchNames) : [],
__typename: 'UpdateChannel',
};
}
function mockUpdateBranches(branchNames: string[]): UpdateBranch[] {
return branchNames.map(branchName => ({
id: 'f9dc4dbb-663f-4a19-8cf2-a783b484d2db',
name: branchName ?? 'default-branch-name',
appId: '123',
createdAt: '2022-12-07T02:24:29.786Z',
updatedAt: '2022-12-07T02:24:29.786Z',
updates: [],
updateGroups: [
[
{
id: '8503286d-4b18-4b38-a0f7-2b9ae09531a0',
group: 'd715bc20-76b5-477b-a060-3f8184aae87a',
message: 'my message',
createdAt: '2022-12-07T02:24:43.487Z',
runtimeVersion: '1.0.0',
platform: 'ios',
manifestFragment: '...',
activityTimestamp: '2022-12-07T02:24:43.487Z',
branchId: '',
awaitingCodeSigningInfo: false,
isGitWorkingTreeDirty: false,
manifestPermalink: '...',
updatedAt: '2022-12-07T02:24:43.487Z',
gitCommitHash: 'abc5baf77eee821b800af97879d19cc3132b46a7',
actor: {
__typename: 'User' as const,
id: 'f42b73a3-ce6c-4059-a825-e5ddafa022f7',
username: 'jonexpo',
} as any,
branch: {
id: 'f9dc4dbb-663f-4a19-8cf2-a783b484d2db',
name: 'production3',
appId: '123',
createdAt: '2022-12-07T02:24:29.786Z',
updatedAt: '2022-12-07T02:24:29.786Z',
updateGroups: [],
updates: [],
__typename: 'UpdateBranch' as const,
},
codeSigningInfo: null,
__typename: 'Update' as const,
},
],
],
__typename: 'UpdateBranch' as const,
}));
}
+67 -4
View File
@@ -1,7 +1,9 @@
import { modifyConfigAsync } from '@expo/config';
import { ExpoConfig } from '@expo/config-types';
import { Platform, Workflow } from '@expo/eas-build-job';
import { EasJsonAccessor } from '@expo/eas-json';
import chalk from 'chalk';
import fs from 'fs-extra';
import { getEASUpdateURL } from '../api';
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
@@ -16,7 +18,7 @@ import { resolveWorkflowPerPlatformAsync } from '../project/workflow';
import { syncUpdatesConfigurationAsync as syncAndroidUpdatesConfigurationAsync } from './android/UpdatesModule';
import { syncUpdatesConfigurationAsync as syncIosUpdatesConfigurationAsync } from './ios/UpdatesModule';
export const DEFAULT_MANAGED_RUNTIME_VERSION = { policy: 'sdkVersion' } as const;
export const DEFAULT_MANAGED_RUNTIME_VERSION = { policy: 'appVersion' } as const;
export const DEFAULT_BARE_RUNTIME_VERSION = '1.0.0' as const;
function getDefaultRuntimeVersion(workflow: Workflow): NonNullable<ExpoConfig['runtimeVersion']> {
@@ -225,7 +227,7 @@ function warnEASUpdatesManualConfig({
/**
* Make sure that the current `app.json` configuration for EAS Updates is set natively.
*/
async function ensureEASUpdatesIsConfiguredNativelyAsync(
async function ensureEASUpdateIsConfiguredNativelyAsync(
graphqlClient: ExpoGraphqlClient,
{
exp,
@@ -252,6 +254,67 @@ async function ensureEASUpdatesIsConfiguredNativelyAsync(
}
}
/**
* Make sure EAS Build profiles are configured to work with EAS Update by adding channels to build profiles.
*/
export async function ensureEASUpdateIsConfiguredInEasJsonAsync(projectDir: string): Promise<void> {
const easJsonPath = EasJsonAccessor.formatEasJsonPath(projectDir);
if (!(await fs.pathExists(easJsonPath))) {
Log.warn(
`EAS Build is not configured. If you'd like to use EAS Build with EAS Update, run ${chalk.bold(
'eas build:configure'
)}, then re-run ${chalk.bold('eas update:configure')} to configure ${chalk.bold(
'eas.json'
)} with EAS Update.`
);
return;
}
try {
const easJsonAccessor = new EasJsonAccessor(projectDir);
await easJsonAccessor.readRawJsonAsync();
easJsonAccessor.patch(easJsonRawObject => {
const easBuildProfilesWithChannels = Object.keys(easJsonRawObject.build).reduce(
(acc, profileNameKey) => {
const buildProfile = easJsonRawObject.build[profileNameKey];
const isNotAlreadyConfigured = !buildProfile.channel && !buildProfile.releaseChannel;
if (isNotAlreadyConfigured) {
return {
...acc,
[profileNameKey]: {
...buildProfile,
channel: profileNameKey,
},
};
}
return {
...acc,
[profileNameKey]: {
...easJsonRawObject.build[profileNameKey],
},
};
},
{}
);
return {
...easJsonRawObject,
build: easBuildProfilesWithChannels,
};
});
await easJsonAccessor.writeAsync();
Log.withTick(`Configured ${chalk.bold('eas.json')}.`);
} catch (error) {
Log.error(`We were not able to configure ${chalk.bold('eas.json')}. Error: ${error}.`);
}
}
/**
* Make sure EAS Update is fully configured in the current project.
* This goes over a checklist and performs the following checks or changes:
@@ -261,7 +324,7 @@ async function ensureEASUpdatesIsConfiguredNativelyAsync(
* - Sets `updates.url` if not set
* - Ensure latest changes are reflected in the native config, if any
*/
export async function ensureEASUpdatesIsConfiguredAsync(
export async function ensureEASUpdateIsConfiguredAsync(
graphqlClient: ExpoGraphqlClient,
{
exp: expWithoutUpdates,
@@ -301,7 +364,7 @@ export async function ensureEASUpdatesIsConfiguredAsync(
});
if (projectChanged || !hasExpoUpdates) {
await ensureEASUpdatesIsConfiguredNativelyAsync(graphqlClient, {
await ensureEASUpdateIsConfiguredNativelyAsync(graphqlClient, {
exp: expWithUpdates,
projectDir,
projectId,
@@ -0,0 +1,58 @@
import { ensureBranchExistsAsync } from '../branch/queries';
import { ChannelNotFoundError } from '../channel/errors';
import { createChannelOnAppAsync } from '../channel/queries';
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
import { ChannelQuery } from '../graphql/queries/ChannelQuery';
export async function getBranchNameFromChannelNameAsync(
graphqlClient: ExpoGraphqlClient,
projectId: string,
channelName: string
): Promise<string> {
let branchName;
try {
const channel = await ChannelQuery.viewUpdateChannelAsync(graphqlClient, {
appId: projectId,
channelName,
});
if (channel.updateBranches.length === 1) {
branchName = channel.updateBranches[0].name;
} else if (channel.updateBranches.length === 0) {
throw new Error(
"Channel has no branches associated with it. Run 'eas channel:edit' to map a branch"
);
} else {
throw new Error(
`Channel has multiple branches associated with it. Instead, use '--branch' instead of '--channel'`
);
}
} catch (error) {
if (!(error instanceof ChannelNotFoundError)) {
throw error;
}
const { branchId } = await ensureBranchExistsAsync(graphqlClient, {
appId: projectId,
branchName: channelName,
});
const {
updateChannel: { createUpdateChannelForApp: newChannel },
} = await createChannelOnAppAsync(graphqlClient, {
appId: projectId,
channelName,
branchId,
});
if (!newChannel) {
throw new Error(
`Could not create channel with name ${channelName} on project with id ${projectId}`
);
}
branchName = channelName;
}
return branchName;
}
+3 -1
View File
@@ -126,7 +126,9 @@ export async function selectUpdateGroupOnBranchAsync(
}),
promptOptions: {
title: 'Load more update groups?',
createDisplayTextForSelectionPromptListItem: updateGroup => formatUpdateTitle(updateGroup[0]),
makePartialChoiceObject: updateGroup => ({
title: formatUpdateTitle(updateGroup[0]),
}),
getIdentifierForQueryItem: updateGroup => updateGroup[0].group,
},
});
+26
View File
@@ -24,6 +24,18 @@ export type FormatUpdateParameter = Pick<Update, 'id' | 'createdAt' | 'message'>
actor?: Maybe<Pick<User, 'username' | 'id'> | Pick<Robot, 'firstName' | 'id'>>;
};
export type UpdateJsonInfo = { branch: string } & Pick<
UpdateFragment,
| 'id'
| 'createdAt'
| 'group'
| 'message'
| 'runtimeVersion'
| 'platform'
| 'manifestPermalink'
| 'gitCommitHash'
>;
export type UpdateGroupDescription = FormatUpdateParameter & {
branch: string;
group: string;
@@ -181,6 +193,20 @@ export function formatUpdateTitle(update: UpdateFragment): string {
)} by ${actorName}, runtimeVersion: ${runtimeVersion}] ${message}`;
}
export function getUpdateGroupJsonInfo(updateGroups: UpdateFragment[]): UpdateJsonInfo[] {
return updateGroups.map(update => ({
id: update.id,
createdAt: update.createdAt,
group: update.group,
branch: update.branch.name,
message: update.message,
runtimeVersion: update.runtimeVersion,
platform: update.platform,
manifestPermalink: update.manifestPermalink,
gitCommitHash: update.gitCommitHash,
}));
}
export function getUpdateGroupDescriptions(
updateGroups: UpdateFragment[][]
): FormattedUpdateGroupDescription[] {
+2
View File
@@ -13,6 +13,8 @@ export function getActorDisplayName(user?: Actor): string {
return user.username;
case 'Robot':
return user.firstName ? `${user.firstName} (robot)` : 'robot';
case 'SSOUser':
return user.username ? `${user.username} (sso user)` : 'sso user';
default:
return 'anonymous';
}
@@ -129,7 +129,7 @@ describe(paginatedQueryWithSelectPromptAsync.name, () => {
promptOptions: {
title: '',
getIdentifierForQueryItem: item => item.id,
createDisplayTextForSelectionPromptListItem: item => 'item: ' + item.value,
makePartialChoiceObject: item => ({ title: 'item: ' + item.value }),
},
});
@@ -179,7 +179,7 @@ describe(paginatedQueryWithSelectPromptAsync.name, () => {
promptOptions: {
title: '',
getIdentifierForQueryItem: item => item.id,
createDisplayTextForSelectionPromptListItem: item => item.value,
makePartialChoiceObject: item => ({ title: item.value }),
},
});
+3 -3
View File
@@ -1,7 +1,7 @@
import {
convertCertificatePEMToCertificate,
convertPrivateKeyPEMToPrivateKey,
signStringRSASHA256AndVerify,
signBufferRSASHA256AndVerify,
validateSelfSignedCertificate,
} from '@expo/code-signing-certificates';
import { ExpoConfig } from '@expo/config';
@@ -116,10 +116,10 @@ export async function getManifestBodyAsync(res: Response): Promise<string | null
}
export function signManifestBody(body: string, codeSigningInfo: CodeSigningInfo): string {
return signStringRSASHA256AndVerify(
return signBufferRSASHA256AndVerify(
codeSigningInfo.privateKey,
codeSigningInfo.certificate,
body
Buffer.from(body, 'utf-8')
);
}
+13 -3
View File
@@ -3,6 +3,12 @@ import uniqBy from './expodash/uniqBy';
const fetchMoreValue = '_fetchMore';
export interface SelectPromptEntry {
title: string;
description?: string;
disabled?: boolean;
}
type BasePaginatedQueryArgs<QueryReturnType extends Record<string, any>> = {
limit: number;
offset: number;
@@ -21,8 +27,9 @@ type PaginatedQueryWithSelectPromptArgs<QueryReturnType extends Record<string, a
BasePaginatedQueryArgs<QueryReturnType> & {
promptOptions: {
readonly title: string;
createDisplayTextForSelectionPromptListItem: (queryItem: QueryReturnType) => string;
makePartialChoiceObject: (queryItem: QueryReturnType) => SelectPromptEntry;
getIdentifierForQueryItem: (queryItem: QueryReturnType) => string;
readonly selectPromptWarningMessage?: string;
};
};
@@ -100,7 +107,7 @@ async function paginatedQueryWithSelectPromptInternalAsync<
const selectionPromptListItems = uniqBy(newAccumulator, queryItem =>
promptOptions.getIdentifierForQueryItem(queryItem)
).map(queryItem => ({
title: promptOptions.createDisplayTextForSelectionPromptListItem(queryItem),
...promptOptions.makePartialChoiceObject(queryItem),
value: promptOptions.getIdentifierForQueryItem(queryItem),
}));
if (areMorePagesAvailable) {
@@ -112,7 +119,10 @@ async function paginatedQueryWithSelectPromptInternalAsync<
const valueOfUserSelectedListItem = await selectAsync<string>(
promptOptions.title,
selectionPromptListItems
selectionPromptListItems,
{
warningMessageForDisabledEntries: promptOptions.selectPromptWarningMessage,
}
);
if (valueOfUserSelectedListItem === fetchMoreValue) {
+7 -2
View File
@@ -1,4 +1,5 @@
import log from '../log';
import chalk from 'chalk';
import GitNoCommitClient from './clients/gitNoCommit';
import NoVcsClient from './clients/noVcs';
import { Client } from './vcs';
@@ -10,7 +11,11 @@ let vcsClient = resolveDefaultVcsClient();
function resolveDefaultVcsClient(): Client {
if (process.env.EAS_NO_VCS) {
if (process.env.NODE_ENV !== 'test') {
log.warn(NO_VCS_WARNING);
// This log might be printed before cli arguments are evaluated,
// so it needs to go to stderr in case command is run in JSON
// only mode.
// eslint-disable-next-line no-console
console.error(chalk.yellow(NO_VCS_WARNING));
}
return new NoVcsClient();
}
+2 -12
View File
@@ -39,7 +39,7 @@ export class Ignore {
if (await fs.pathExists(easIgnorePath)) {
this.ignoreMapping = [
['', createIgnore().add(DEFAULT_IGNORE)],
['', createIgnore().add(await this.readIgnoreFileAsync(easIgnorePath))],
['', createIgnore().add(await fs.readFile(easIgnorePath, 'utf-8'))],
];
return;
}
@@ -57,7 +57,7 @@ export class Ignore {
ignoreFilePaths.map(async filePath => {
return [
filePath.slice(0, filePath.length - GITIGNORE_FILENAME.length),
createIgnore().add(await this.readIgnoreFileAsync(path.join(this.rootDir, filePath))),
createIgnore().add(await fs.readFile(path.join(this.rootDir, filePath), 'utf-8')),
] as const;
})
);
@@ -72,16 +72,6 @@ export class Ignore {
}
return false;
}
private async readIgnoreFileAsync(filePath: string): Promise<string> {
const fileContents = await fs.readFile(filePath, 'utf-8');
const lines = fileContents.split('\n');
// Strip trailing '\'. This logic can be removed after fix upstream is released.
// https://github.com/kaelzhang/node-ignore/issues/81
return lines
.map((line: string) => (line.slice(-1) === '\\' ? line.slice(0, -1) : line))
.join('\n');
}
}
export async function makeShallowCopyAsync(src: string, dst: string): Promise<void> {
+6 -6
View File
@@ -1,28 +1,28 @@
{
"name": "@expo/eas-json",
"description": "A library for interacting with eas.json",
"version": "2.8.0",
"version": "3.3.2",
"author": "Expo <[email protected]>",
"bugs": "https://github.com/expo/eas-cli/issues",
"dependencies": {
"@babel/code-frame": "7.18.6",
"@expo/eas-build-job": "0.2.97",
"@expo/eas-build-job": "0.2.102",
"chalk": "4.1.2",
"env-string": "1.0.1",
"fs-extra": "10.1.0",
"golden-fleece": "1.0.9",
"joi": "17.6.4",
"joi": "17.7.0",
"log-symbols": "4.1.0",
"semver": "7.3.8",
"terminal-link": "2.1.1",
"tslib": "2.4.0"
"tslib": "2.4.1"
},
"devDependencies": {
"@types/babel__code-frame": "7.0.3",
"@types/fs-extra": "9.0.13",
"memfs": "3.4.7",
"memfs": "3.4.13",
"rimraf": "3.0.2",
"typescript": "4.8.4"
"typescript": "4.9.4"
},
"engines": {
"node": ">=14.0.0"
+44 -2
View File
@@ -38,7 +38,7 @@
"When using remote, the `autoIncrement` is based on the values stored on EAS servers."
]
},
"promptToConfigurePushNotifications" : {
"promptToConfigurePushNotifications": {
"type": "boolean",
"description": "Specifies where EAS CLI should prompt to configure Push Notifications credentials. Defaults to true.",
"default": true
@@ -176,6 +176,19 @@
"description": "List of paths (or patterns) where EAS Build is going to look for the build artifacts. Use `applicationArchivePath` to specify the path for uploading the application archive. Build artifacts are uploaded even if the build fails. See: https://github.com/mrmlnc/fast-glob#pattern-syntax",
"markdownDescription": "List of paths (or patterns) where EAS Build is going to look for the build artifacts. Use `applicationArchivePath` to specify the path for uploading the application archive. Build artifacts are uploaded even if the build fails. EAS Build uses the `fast-glob` npm package for pattern matching ([see their README to learn more about the syntax you can use](https://github.com/mrmlnc/fast-glob#pattern-syntax))."
},
"resourceClass": {
"description": "The resource class that will be used to run this build, supported by both Android and iOS workers. Learn more: https://docs.expo.dev/build-reference/infrastructure/",
"markdownDescription": "The resource class that will be used to run this build, supported by both Android and iOS workers. [Learn more](https://docs.expo.dev/build-reference/infrastructure/)",
"default": "default",
"anyOf": [
{
"enum": ["default", "medium"]
},
{
"type": "string"
}
]
},
"android": {
"$ref": "#/definitions/BuildProfileAndroid"
},
@@ -222,6 +235,19 @@
}
]
},
"resourceClass": {
"description": "The Android-specific resource class that will be used to run this build. Learn more: https://docs.expo.dev/build-reference/infrastructure/",
"markdownDescription": "The Android-specific resource class that will be used to run this build. [Learn more](https://docs.expo.dev/build-reference/infrastructure/)",
"default": "default",
"anyOf": [
{
"enum": ["default", "medium", "large"]
},
{
"type": "string"
}
]
},
"ndk": {
"type": "string",
"description": "The version of Android NDK."
@@ -311,7 +337,23 @@
"macos-big-sur-11.4-xcode-13.0",
"macos-big-sur-11.4-xcode-12.5"
],
"markdownEnumDescriptions": ["`macos-monterey-12.6-xcode-14.0`", "`macos-monterey-12.6-xcode-14.1`"]
"markdownEnumDescriptions": [
"`macos-monterey-12.6-xcode-14.0`",
"`macos-monterey-12.6-xcode-14.1`"
]
},
{
"type": "string"
}
]
},
"resourceClass": {
"description": "The iOS-specific resource class that will be used to run this build. Learn more: https://docs.expo.dev/build-reference/infrastructure/",
"markdownDescription": "The iOS-specific resource class that will be used to run this build. [Learn more](https://docs.expo.dev/build-reference/infrastructure/)",
"default": "default",
"anyOf": [
{
"enum": ["default", "medium", "m1-medium", "intel-medium"]
},
{
"type": "string"
@@ -349,3 +349,53 @@ test('get profile names', async () => {
const allProfileNames = await EasJsonUtils.getBuildProfileNamesAsync(accessor);
expect(allProfileNames.sort()).toEqual(['blah', 'production'].sort());
});
test('invalid resourceClass at build profile root', async () => {
await fs.writeJson('/project/eas.json', {
build: {
production: {
resourceClass: 'm1-experimental',
},
},
});
const accessor = new EasJsonAccessor('/project');
await expect(
EasJsonUtils.getBuildProfileAsync(accessor, Platform.IOS, 'production')
).rejects.toThrowError(/build.production.resourceClass.*must be one of/);
});
test('iOS-specific resourceClass', async () => {
await fs.writeJson('/project/eas.json', {
build: {
production: {
ios: {
resourceClass: 'm1-medium',
},
},
},
});
const accessor = new EasJsonAccessor('/project');
await expect(
EasJsonUtils.getBuildProfileAsync(accessor, Platform.IOS, 'production')
).resolves.not.toThrow();
});
test('Android-specific resourceClass', async () => {
await fs.writeJson('/project/eas.json', {
build: {
production: {
android: {
resourceClass: 'large',
},
},
},
});
const accessor = new EasJsonAccessor('/project');
await expect(
EasJsonUtils.getBuildProfileAsync(accessor, Platform.ANDROID, 'production')
).resolves.not.toThrow();
});
+8 -1
View File
@@ -15,7 +15,14 @@ const customErrorMessageHandlers: ((err: ValidationError) => void)[] = [
// Ask user to upgrade eas-cli version or check the docs when image is invalid.
(err: ValidationError) => {
for (const detail of err.details) {
if (detail.path[detail.path.length - 1] === 'image') {
// image should be only placed under 'build.profilename.platform.image' key
// if it's not the case show standard Joi error
if (
detail.path.length === 4 &&
detail.path[0] === 'build' &&
['ios', 'android'].includes(detail.path[2].toString()) &&
detail.path[3] === 'image'
) {
throw new InvalidEasJsonError(
chalk.red(
`Specified build image '${
+18
View File
@@ -2,6 +2,21 @@ import { Android, Ios } from '@expo/eas-build-job';
import Joi from 'joi';
import semver from 'semver';
import { ResourceClass } from './types';
const AllowedCommonResourceClasses: ResourceClass[] = [ResourceClass.DEFAULT, ResourceClass.MEDIUM];
const AllowedAndroidResourceClasses: ResourceClass[] = [
...AllowedCommonResourceClasses,
ResourceClass.LARGE,
];
const AllowedIosResourceClasses: ResourceClass[] = [
...AllowedCommonResourceClasses,
ResourceClass.M1_MEDIUM,
ResourceClass.INTEL_MEDIUM,
];
const CacheSchema = Joi.object({
disabled: Joi.boolean(),
key: Joi.string().max(128),
@@ -24,6 +39,7 @@ const CommonBuildProfileSchema = Joi.object({
expoCli: Joi.string().empty(null).custom(semverCheck),
env: Joi.object().pattern(Joi.string(), Joi.string().empty(null)),
autoIncrement: Joi.alternatives().try(Joi.boolean()),
resourceClass: Joi.string().valid(...AllowedCommonResourceClasses),
});
const AndroidBuildProfileSchema = CommonBuildProfileSchema.concat(
@@ -38,6 +54,7 @@ const AndroidBuildProfileSchema = CommonBuildProfileSchema.concat(
Joi.boolean(),
Joi.string().valid('version', 'versionCode')
),
resourceClass: Joi.string().valid(...AllowedAndroidResourceClasses),
artifactPath: Joi.string(),
applicationArchivePath: Joi.string(),
@@ -58,6 +75,7 @@ const IosBuildProfileSchema = CommonBuildProfileSchema.concat(
Joi.string().valid('version', 'buildNumber')
),
simulator: Joi.boolean(),
resourceClass: Joi.string().valid(...AllowedIosResourceClasses),
image: Joi.string().valid(...Ios.builderBaseImages),
bundler: Joi.string().empty(null).custom(semverCheck),
+16
View File
@@ -5,6 +5,21 @@ export enum CredentialsSource {
REMOTE = 'remote',
}
export enum ResourceClass {
DEFAULT = 'default',
LARGE = 'large',
/**
* @deprecated use M1_MEDIUM instead
* @experimental
* This resource class is not yet ready to be used in production. For testing purposes only. Might be deprecated / deleted at any time.
*/
M1_EXPERIMENTAL = 'm1-experimental',
M1_MEDIUM = 'm1-medium',
M1_LARGE = 'm1-large',
INTEL_MEDIUM = 'intel-medium',
MEDIUM = 'medium',
}
export type DistributionType = 'store' | 'internal';
export type IosEnterpriseProvisioning = 'adhoc' | 'universal';
@@ -22,6 +37,7 @@ export interface CommonBuildProfile {
developmentClient?: boolean;
prebuildCommand?: string;
autoIncrement?: boolean;
resourceClass?: ResourceClass;
buildArtifactPaths?: string[];
node?: string;
+1
View File
@@ -8,6 +8,7 @@ export {
DistributionType,
IosEnterpriseProvisioning,
IosVersionAutoIncrement,
ResourceClass,
} from './build/types';
export { EasJsonAccessor } from './accessor';
export { EasJsonUtils } from './utils';
+6 -6
View File
@@ -18,22 +18,22 @@
"node": ">=14.16"
},
"dependencies": {
"chalk": "5.1.2",
"chalk": "5.2.0",
"dateformat": "4.5.1",
"fs-extra": "10.1.0",
"lodash-es": "4.17.21",
"marked": "3.0.4",
"semver": "7.3.7",
"tslib": "2.4.0"
"semver": "7.3.8",
"tslib": "2.4.1"
},
"devDependencies": {
"@types/dateformat": "3.0.1",
"@types/fs-extra": "9.0.13",
"@types/lodash-es": "4.17.6",
"@types/node": "18.0.4",
"@types/semver": "7.3.10",
"@types/node": "18.11.18",
"@types/semver": "7.3.13",
"ts-node": "10.9.1",
"typescript": "4.7.4"
"typescript": "4.9.4"
},
"volta": {
"node": "18.6.0",
+24 -24
View File
@@ -76,15 +76,15 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.10.3.tgz#7a8f2838603ea314d1d22bb3171d899e15c57bd5"
integrity sha512-ho3Ruq+fFnBrZhUYI46n/bV2GjwzSkwuT4dTf0GkuNFmnb8nq4ny2z9JEVemFi6bdEJanHLlYfy9c6FN9B9McQ==
"@types/node@18.0.4":
version "18.0.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.4.tgz#48aedbf35efb3af1248e4cd4d792c730290cd5d6"
integrity sha512-M0+G6V0Y4YV8cqzHssZpaNCqvYwlCiulmm0PwpNLF55r/+cT8Ol42CHRU1SEaYFH2rTwiiE1aYg/2g2rrtGdPA==
"@types/node@18.11.18":
version "18.11.18"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f"
integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==
"@types/[email protected]0":
version "7.3.10"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.10.tgz#5f19ee40cbeff87d916eedc8c2bfe2305d957f73"
integrity sha512-zsv3fsC7S84NN6nPK06u79oWgrPVd0NvOyqgghV1haPaFcVxIrP4DLomRwGAXk0ui4HZA7mOcSFL98sMVW9viw==
"@types/[email protected]3":
version "7.3.13"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91"
integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==
acorn-walk@^8.1.1:
version "8.2.0"
@@ -101,10 +101,10 @@ arg@^4.1.0:
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
chalk@5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.1.2.tgz#d957f370038b75ac572471e83be4c5ca9f8e8c45"
integrity sha512-E5CkT4jWURs1Vy5qGJye+XwCkNj7Od3Af7CP6SujMetSMkLs8Do2RWJK5yx1wamHV/op8Rz+9rltjaTQWDnEFQ==
chalk@5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.2.0.tgz#249623b7d66869c673699fb66d65723e54dfcfb3"
integrity sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==
create-require@^1.1.0:
version "1.1.1"
@@ -166,10 +166,10 @@ [email protected]:
resolved "https://registry.yarnpkg.com/marked/-/marked-3.0.4.tgz#b8a1539e5e05c6ea9e93f15c0bad1d54ce890406"
integrity sha512-jBo8AOayNaEcvBhNobg6/BLhdsK3NvnKWJg33MAAPbvTWiG4QBn9gpW1+7RssrKu4K1dKlN+0goVQwV41xEfOA==
[email protected].7:
version "7.3.7"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f"
integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==
[email protected].8:
version "7.3.8"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
dependencies:
lru-cache "^6.0.0"
@@ -192,15 +192,15 @@ [email protected]:
v8-compile-cache-lib "^3.0.1"
yn "3.1.1"
[email protected].0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
[email protected].1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e"
integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==
typescript@4.7.4:
version "4.7.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235"
integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==
typescript@4.9.4:
version "4.9.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.4.tgz#a2a3d2756c079abda241d75f149df9d561091e78"
integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==
universalify@^2.0.0:
version "2.0.0"
Generated
+1642 -1286
View File
File diff suppressed because it is too large. Load diff