Compare commits

...
85 Commits
Author SHA1 Message Date
Dominik Sokal 9fde84211c test - wip 2022-07-11 13:51:34 +02:00
Dominik Sokal b2d0f862b6 configure jest for ESM 2022-07-11 11:38:02 +02:00
Dominik Sokal ce35266710 [scripts] add script for testing ESM imports 2022-07-11 10:53:12 +02:00
Dominik Sokal b1df501672 [eas-cli] update run script 2022-07-11 10:53:12 +02:00
Dominik Sokal 2ecd09031e [eas-cli] upgrade @oclif/core 2022-07-11 10:53:12 +02:00
Dominik Sokal 677578cb42 install ts-node 2022-07-11 10:53:12 +02:00
Dominik Sokal 78d82f62ce [eas-cli] rename patch-readme.js -> patch-readme.cjs 2022-07-11 10:53:12 +02:00
Dominik Sokal d442ddede6 require node >= 14.16 2022-07-11 10:53:12 +02:00
Dominik Sokal 293ee3d8fb convert root package to esm 2022-07-11 10:53:12 +02:00
Dominik Sokal 7c5371767c fix imports 2022-07-11 10:53:09 +02:00
Dominik Sokal 28182e7aef configure modules as ESM 2022-07-05 13:05:00 +02:00
Dominik Sokal 04a8b08f59 [ENG-4579][scripts] convert to ESM (#1192)
* upgrade typescript to 4.7.4

* [scripts] add extensions to imports

* [scripts] configure as ESM

* [scripts] fix after converting to ESM

* [scripts] fix lint

* [scripts] require node >= 14.16

* [scripts] add node: protocol

* add scripts/build to .gitignore

* [scripts] add typecheck script

* add workflow for testing scripts

* address PR feedback
2022-07-04 11:50:57 +02:00
Cedric van Putten 8bce9b19b2 [eas-cli] Remove deprecated idfa and price tier from store config (#1193)
* [eas-cli] Drop deprecated idfa from store config

* [eas-cli] Drop deprecated price tier from store config

* update CHANGELOG.md
2022-07-02 02:52:35 +02:00
Cedric van Putten d3d6d41f9f [eas-cli] Improve store config categories configuration (#1187)
* [eas-cli] Improve EAS metadata category configuration

* [eas-cli] Update category types for apple store configuration

* [eas-cli] Add tests for the behavior of the categories from store configuration

* [eas-cli] Update apple store config with new categories

* [eas-cli] Simplify parent vs normal categories in schema

* [eas-cli] Fix serialization issue with empty secondary sub category

* [eas-cli] Relax the apple category types to allow strings

* [eas-cli] Fix an issue in reader related to the category types

* [eas-cli] Add comments about string vs category enum

* update CHANGELOG.md
2022-07-02 02:02:37 +02:00
Brent Vatne 0534328dfc [github] Add issue triage workflows 2022-06-30 17:45:44 -07:00
Cedric van Putten d0b9af2553 [eas-cli] Add review details to metadata store configuration (#1184)
* [eas-cli] Tweak the store configuration validationf or review

* [eas-cli] Implement review details in metadata

* [eas-cli] Use valid fixtures in config tests

* [eas-cli] Add markdown description for review notes

* [eas-cli] Add app review detail task description

* update CHANGELOG.md
2022-06-29 06:17:10 -07:00
Cedric van Putten 80674a3451 [eas-cli] Improve store configuration defaults and schema configuration (#1183)
* [eas-cli] Avoid setting automaticRelease for manual releases in config

* [eas-cli] Use same default app name as schema

* [eas-cli] Prefer releaseNotes over whatsNew in apple info

* [eas-cli] Drop deprecated gamblingAndContest from schema

* [eas-cli] Use better defaults for advisory

* [eas-cli] Remove type from enum as its not required by spec

* [eas-cli] Remove $ref and description workaround for draft 6

* [eas-cli] Update kids age rating description

* [eas-cli] Remove default app title

* update CHANGELOG.md
2022-06-28 05:24:32 -07:00
kirb 41b48a80be [eas-cli] truncates long messages for eas update command (#1178) 2022-06-24 15:27:52 -07:00
Dominik Sokal 3d5b77a263 [ENG-5262] fix URLs returned from AWS S3 (#1179)
* fix URLs returned from AWS S3

* update CHANGELOG.md
2022-06-24 11:17:49 +02:00
Chris WalterandDominik Sokal fa25d259d9 [1/1] Support resource-class flag in eas-cli (#1138)
* [1/1] Support build-resource-class flag in eas-cli

# Why
We want to add a flag to allow users to specify resource-class when they
run `eas build`. The flag is experimental for now, and we haven't
decided exactly how we'll incorporate the resource classes into plan
pricing. But this PR doesn't deal with that - it just makes the
necessary changes to eas-cli to support specifying a resource class when
running `eas build`.

# How
Add a new enum for BuildResourceClass that matches the enum created
for GraphQL in universe/server/www. Then create a new flag
`build-resource-class` whose options are the values of the
BuildResourceClass enum. Then add some validation to prevent resource
classes being used for incompatible platforms (e.g. prevent `-p ios
--build-resource-class=ANDROID_LARGE`). Finally, pass along the flag
value to the call to the WWW graphql mutations for BuildAndroid and
BuildiOS.

# Test Plan
```
yarn test
```
See test plan on this PR for more thorough e2e testing summary:
https://github.com/expo/universe/pull/9800

* Update packages/eas-cli/src/commands/build/index.ts

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

* Apply suggestions from code review

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

* Address PR comments

* Regenerate graphql from staging

* update CHANGELOG.md

Co-authored-by: Dominik Sokal <[email protected]>
2022-06-23 20:11:20 -07:00
Cedric van PuttenandEvan Bacon 26596f32e9 [eas-cli] Allow users to skip metadata validation (#1175)
* [eas-cli] Allow users to skip validation when schema has an issue

* [eas-cli] Make sure instructions are visible

* update CHANGELOG.md

* [eas-cli] Remove instructions from confirm async

* [eas-cli] Fix typo in confirm question

* [eas-cli] Reword warning about ignoring store config issues

Co-authored-by: Evan Bacon <[email protected]>

* [eas-cli] Reword confirmation question of ignoring issues

Co-authored-by: Evan Bacon <[email protected]>

Co-authored-by: Evan Bacon <[email protected]>
2022-06-23 05:13:39 -07:00
Cedric van Putten 031c610d58 [eas-cli] Update validation rules for metadata info locales (#1174)
* [eas-cli] Update validation rules for metadata info locales

* Add missing codeowner for metadata schema

* update CHANGELOG.md

* Fix path in codeowners
2022-06-23 04:43:28 -07:00
Dominik Sokal fcb5beccb4 update CHANGELOG.md 2022-06-23 09:16:57 +02:00
kirb 3003a712f6 [eas-cli] include bundler output in terminal for eas update (#1171) 2022-06-22 10:46:31 -07:00
Cedric van Putten e89f030c29 fix CHANGELOG 2022-06-17 16:02:19 +02:00
Expo CI 3e224f9583 update CHANGELOG.md 2022-06-15 21:56:43 +00:00
Cedric van Putten db338b2b78 v0.54.1 2022-06-15 23:42:44 +02:00
Cedric van Putten 971c8e4010 [eas-cli] Add link to ASC after successful metadata sync (#1168)
* [eas-cli] Add link to ASC after successful metadata sync

* update CHANGELOG.md
2022-06-15 23:26:36 +02:00
Cedric van Putten df64a59354 [eas-cli] Surface metadata cause errors in logging output (#1167)
* [eas-cli] Surface metadata cause errors in logging output

* update CHANGELOG.md
2022-06-15 23:26:16 +02:00
Cedric van Putten e5d80fcb6d [eas-cli] Add schemas to the bundled files (#1166)
* [eas-cli] Add schemas to the bundled files

* update CHANGELOG.md
2022-06-15 22:05:05 +02:00
Expo CI 4088ea3e43 update CHANGELOG.md 2022-06-15 17:01:30 +00:00
Kirby Cofino edd42186d9 v0.54.0 2022-06-15 09:53:45 -07:00
Wojciech Kozyra e6ba63cfd0 [eas-cli] Fix regression for default submit profile (#1163)
* [eas-cli] Fix regression for default submit profile

* Update CHANGELOG
2022-06-15 13:02:24 +02:00
Wojciech Kozyra 7b60901bb1 [eas-cli] update @expo/eas-build-job (#1162)
* update eas-build-job

* update CHANGELOG.md
2022-06-15 12:01:15 +02:00
Wojciech Kozyra a551e9010a add default codeowners (#1161) 2022-06-15 10:54:02 +02:00
Wojciech KozyraandDominik Sokal 95441798ed Update issue template (expo doctor output) (#1160)
* Update issue template (expo doctor output)

* Update .github/ISSUE_TEMPLATE/bug_report.yml

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

Co-authored-by: Dominik Sokal <[email protected]>
2022-06-15 10:49:08 +02:00
Wojciech Kozyra 814f863a63 fix build error 2022-06-15 10:44:22 +02:00
Wojciech Kozyra 283f086b25 [eas-cli] Remove fallback for legacy format in eas.json (#1158)
* remove support for deprecated eas.json formats

* update CHANGELOG.md
2022-06-15 10:39:48 +02:00
Dominik Sokal 7da01333c6 Update CHANGELOG.md 2022-06-15 09:30:07 +02:00
Cedric van PuttenandWojciech Kozyra c057eaa098 [eas-cli] Add metadata commands (#1136)
* [eas-cli] Add metadata commands

* Add myself as codeowner to the metadata

* [eas-cli] Hide the metadata commands for now

* Add metadata changelog entry

* [eas-cli] Update metadata configure command description

* [eas-cli] Drop non-interactive due to limitations in AppStoreApi

* [eas-cli] Reimplement credentials context for metadata

* [eas-cli] Drop non-interactive flag in metadata command

* [eas-cli] Drop args from metadata:configure

Co-authored-by: Wojciech Kozyra <[email protected]>

* [eas-cli] Add retroactive code review changes (#1147)

* [eas-cli] Add public access modifiers to classes

* [eas-cli] Add specific types to date precision remover

* [eas-cli] Add try catch around writing json to always unsubscribe

* [eas-cli] Add async return await to uploadAsync log methods

* [eas-cli] Fix date precision type and test

* [eas-cli] Use submission profile bundle id if defined

* [eas-cli] Drop catch from IO try catch block

* [eas-cli] Move unique helper to global utils

* [eas-cli] Prefer nullish coalescing

* [eas-cli] Move metadata commands to pull and push

* [eas-cli] Drop the platform option from the push command

* [eas-cli] Remove alias and reword descriptions

* [eas-cli] Auto-configure eas.json with metadata when missing (#1156)

* [eas-cli] Polish the command output for release (#1159)

* [eas-cli] Finalize metadata logging output

* [eas-cli] Fix logging validation errors when store.config.json is not found

* [eas-cli] Make all localized entites bold

* [eas-cli] Make version string visible in logs

* [eas-cli] Add note about early beta

* [eas-cli] Remove hidden from meta commands

* [eas-cli] Add metadata topic

* [eas-cli] Rename eas metadata to eas metadata:push in logging

* [eas-cli] Remove unused arg flag from push

Co-authored-by: Wojciech Kozyra <[email protected]>
2022-06-14 17:46:59 +02:00
Will Schurman 968fdd221c [eas-cli] Limit concurrent asset uploads (#1153) 2022-06-13 13:27:51 -07:00
Dominik Sokal 6d28e0eecc Update CHANGELOG.md 2022-06-13 08:50:03 +02:00
kirb a2b4d2dbd2 [eas-cli] add fetching additional pages for update --republish (#1148)
- add update/getUpdatesToRepublishInteractiveAsync and tests
2022-06-10 19:05:26 -07:00
kirb 660c996602 [eas-cli] improve update terminal output (#1152)
- add additional information to publish command output such as update ids and website links
- https://linear.app/expo/issue/ENG-4589/improve-publish-command
- add additional context to uploadAssetsAsync return type
- add real-time text to upload spinner showing upload progress
- remove ) from website link on unsupported terminals
2022-06-10 18:06:50 -07:00
kirb 35ede265ed [eas-cli] make viewBranchAsync updates limit configurable (#1144)
* make viewBranchAsync limit configurable
* add tests for updates/ensureChannelExistsAsync
* rename PAGE_LIMIT to viewBranchUpdatesQueryUpdateLimit
* generate graphql
2022-06-08 14:06:45 -07:00
Dominik Sokal cf02f075d7 Update CHANGELOG.md 2022-06-08 12:05:02 +02:00
Dominik Sokal a2027eabd2 fix CHANGELOG 2022-06-08 12:02:29 +02:00
Expo CI 4ef239c59c update CHANGELOG.md 2022-06-07 19:11:58 +00:00
Kirby Cofino 3610eee2b5 v0.53.1 2022-06-07 12:00:02 -07:00
Kirby Cofino 54ae94f532 upgrade eas-cli-local-build-plugin to 0.0.85 2022-06-07 11:59:37 -07:00
kirb c68bf3e26f [eas-cli] lower page limit for UpdateQueries (#1119)
* [eas-cli] lower page limit for UpdateQueries

- lower page limit from 10_000 to 300 to avoid timeouts on branches with many updates.
  we do not fetch the full history of updates anymore for `--republish`, etc.
2022-06-07 11:41:33 -07:00
Cedric van Putten 940e3f6d40 [eas-cli] Add metadata root actions and error handling (#1135)
* [eas-cli] Add metadata root actions and error handling

* [eas-cli] Update download and upload metadata methods to new ctx
2022-06-04 16:22:26 +02:00
Cedric van PuttenandEvan Bacon 4c6226b90b [eas-cli] Add metadata app store task runner (#1133)
* [eas-cli] Add metadata app store task runner

* [eas-cli] Use expect error over ignore

Co-authored-by: Evan Bacon <[email protected]>

* [eas-cli] Remove unused ts directive

* [eas-cli] Add download task tests

Co-authored-by: Evan Bacon <[email protected]>
2022-06-02 17:04:59 -07:00
Cedric van Putten 1341bb18d1 [eas-cli] Add metadata telemetry increase visibility on potential issues (#1132) 2022-06-02 13:59:34 -07:00
Cedric van Putten beac65ce53 [eas-cli] Add metadata config validation using json schema (#1131)
* [eas-cli] Add metadata config validation using json schema

* [eas-cli] Fix typo in privacy choices validation

* [eas-cli] Fix typo in fixture test
2022-06-02 13:58:51 -07:00
Cedric van Putten a8cc54d409 [eas-cli] Add metadata context based on submission contexts (#1134)
* [eas-cli] Add metadata context based on submission contexts

* [eas-json] Add submission meta property to config

* [eas-cli] Make exp optional in the metdata context

* [eas-cli] Fix misleading docblock on metadata context

* [eas-cli] Fix pass through exp config in metadata context

* [eas-cli] Import ios submission profile type through entrypoint

* [eas-cli] Rename metadata file to filename in context

* [eas-cli] Move credential context outside metadata context

* [eas-cli] Rename meta to metadataPath in profile config

* [eas-cli] Drop nonInteractive from metadata because of AppStoreApi limitations

* [eas-cli] Use singular store in bundle identifier doc
2022-06-02 17:06:04 +02:00
Cedric van PuttenandEvan Bacon 6a639bd556 [eas-cli] Add metadata store config serializers (#1130)
* [eas-cli] Add metadata store config serializers

* [eas-cli] Add version reader doc to avoid ambiguity

Co-authored-by: Evan Bacon <[email protected]>

* [eas-cli] Add tests for date precision utility

Co-authored-by: Evan Bacon <[email protected]>
2022-06-02 05:31:56 -07:00
Dominik Sokal dde9685b38 add common error code - fastlane timeout (#1129)
* add common error code - fastlane timeout

* address PR feedback

* update CHANGELOG.md
2022-06-01 11:55:53 +02:00
Dominik Sokal 5b3a76a5b5 [ENG-5022] print learn more link before uploading archive to S3 (#1127)
* print learn more link before uploading archive to S3

* update CHANGELOG.md
2022-05-31 09:54:25 +02:00
Dominik Sokal 513e09157b Update CHANGELOG.md 2022-05-30 12:28:49 +02:00
Expo CI 69a939c635 update CHANGELOG.md 2022-05-30 10:22:18 +00:00
Dominik Sokal 58156545d0 v0.53.0 2022-05-30 12:14:58 +02:00
Dominik Sokal 8a52b5c401 upgrade eas-cli-local-build-plugin to 0.0.82 2022-05-30 12:14:52 +02:00
Dominik Sokal 14d4c7b234 use single version of @oclif/core (#1115)
* upgrade @oclif/core

* Use forked @oclif/plugin-autocomplete and @oclif/plugin-help

* upgrade @expo/plugin-warn-if-update-available

* update CHANGELOG
2022-05-30 12:09:32 +02:00
Wojciech Kozyra fd17c96b3b [eas-cli] use getExpoConfig wrapper (#1122)
* [eas-cli] use getConfig wrapper

* update CHANGELOG.md
2022-05-26 11:05:09 +02:00
Evan Bacon 833a5465c5 fix: match capability types more accurately (#1112)
* fix: match capability types more accurately and prevent disabling unrelated types

* update CHANGELOG.md
2022-05-23 11:20:54 -05:00
Dominik Sokal f0c958e58b Drop support for node <14 (#1098)
* drop support for node 12 and 13

* update volta pinned node and yarn versions

* update node version in CI

* upgrade memfs to latest
2022-05-19 10:21:09 +02:00
Dominik Sokal 607838c8e1 [ENG-4968] better spinner placement for multiple builds (#1105)
* better spinner placement for multiple builds

* update CHANGELOG.md
2022-05-17 09:10:00 +02:00
Dominik Sokal 34ecd38304 Update dependencies (#1095)
* update outdated deps

* [eas-cli] regenerate GraphQL code

* [eas-cli] fix tests

* [scripts] upgrade deps

* [eas-cli] fix lint warnings

* update CHANGELOG.md
2022-05-11 11:20:22 +02:00
Will Schurman c4adf7056e [eas-cli] Replace asMock with jest.mocked (#1089) 2022-05-02 12:56:16 -07:00
Expo CI 0e7f326de2 update CHANGELOG.md 2022-04-26 13:10:13 +00:00
Wojciech Kozyra bbc8b1ac76 v0.52.0 2022-04-26 14:49:58 +02:00
Wojciech Kozyra 3db2a69183 upgrade eas-cli-local-build-plugin to 0.0.78 2022-04-26 14:49:48 +02:00
Wojciech Kozyra 51155bb2b4 [eas-cli] update eas-build-job (#1084) 2022-04-26 14:11:52 +02:00
Wojciech Kozyra 30ec5f967b [eas-cli] Support target specific entitlements (#1078)
* [eas-cli] Support target specific entitlements

* reiview feedback

* fix tests

* review feedback

* update CHANGELOG.md
2022-04-26 14:11:30 +02:00
Expo CI 89dda20149 update CHANGELOG.md 2022-04-19 10:40:33 +00:00
Dominik Sokal b591698c31 v0.51.0 2022-04-19 12:32:52 +02:00
Cedric van Putten 66543b658b [eas-cli] Enable update bundle output when debugging (#1070)
* [eas-cli] Enable update bundle output when debugging

* update CHANGELOG.md
2022-04-19 03:15:36 -07:00
Evan Bacon 4769048578 Bump @expo/[email protected] (#1064)
* Bump @expo/[email protected]

* Update CHANGELOG.md
2022-04-14 11:56:15 -05:00
Will Schurman 64c1e47674 [eas-cli] Add non-interactive flag to eas update command (#1066) 2022-04-14 09:39:42 -07:00
Dominik Sokal be3a86abda submit - add custom error message for expired apple certs problem (#1068)
* submit - add custom error message for expired apple certs problem

* PR feedback

* update CHANGELOG.md
2022-04-14 11:49:07 +02:00
Dominik Sokal eb2ca117fc [ENG-4615] unify google service account prompts (#1063)
* unify google service account prompt

* update CHANGELOG.md

* fix tests
2022-04-14 09:50:39 +02:00
Dominik Sokal 5043385077 fix expo-cli reference 2022-04-12 11:54:56 +02:00
Will Schurman bb4c08a52a [eas-cli] Require private-key-path to be specified for updating when code signing configured (#1059) 2022-04-11 10:42:31 -07:00
Expo CI 8b75057fa1 update CHANGELOG.md 2022-04-11 08:27:15 +00:00
532 changed files with 12225 additions and 5005 deletions

No files matched your search

View File
File renamed without changes.
+1 -1
View File
@@ -37,7 +37,7 @@ body:
required: true
attributes:
label: Environment
description: Run `npx expo-env-info` and paste the output here.
description: Run `npx expo-env-info` and `expo doctor`, and paste the output here.
- type: textarea
validations:
required: false
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
node-version: 18
- name: Checkout Pull Request
run: hub pr checkout ${{ github.event.issue.number }}
env:
+146
View File
@@ -0,0 +1,146 @@
name: Issue Triage
on:
issues:
types: [labeled]
jobs:
needs-repro:
runs-on: ubuntu-20.04
if: "${{ contains(github.event.label.name, 'incomplete issue: missing or invalid repro') }}"
steps:
- uses: actions/github-script@v3
with:
github-token: ${{ secrets.EXPO_BOT_GITHUB_TOKEN }}
script: |
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `Hi there! It looks like your issue requires a minimal reproducible example, but it is invalid or absent. Please prepare such an example and share it in a new issue.
**The best way to get attention to your issue is to provide a clean and easy way for a developer to reproduce the issue on their own machine.** Please do not provide your entire project, or a project with more code than is necessary to reproduce the issue.
A side benefit of going through the process of narrowing down the minimal amount of code needed to reproduce the issue is that you may get lucky and discover that the bug is due to a mistake in your application code that you can quickly fix on your own.
### Resources
- ["How to create a Minimal, Reproducible Example"](https://stackoverflow.com/help/minimal-reproducible-example)
- ["How to narrow down the source of an error"](https://expo.fyi/manual-debugging)
### Common concerns
#### "I've only been able to reproduce it in private, proprietary code"
You may not have spent enough time narrowing down the root cause of the issue. Try out the techniques discussed in this [manual debugging guide](https://expo.fyi/manual-debugging) to learn how to isolate the problem from the rest of your codebase.
#### "I didn't have time to create one"
That's understandable, it can take some time to prepare. We ask that you hold off on filing an issue until you are able to fully complete the required fields in the issue template.
#### "You can reproduce it by yourself by creating a project and following these steps"
This is useful knowledge, but it's still valuable to have the resulting project that is produced from running the steps, where you have verified you can reproduce the issue.
`})
github.issues.update({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
state: 'closed'
})
needs-info:
runs-on: ubuntu-20.04
if: "${{ contains(github.event.label.name, 'incomplete issue: missing info') }}"
steps:
- uses: actions/github-script@v3
with:
github-token: ${{ secrets.EXPO_BOT_GITHUB_TOKEN }}
script: |
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `Hello! There isn't enough information provided in your issue description for us to be able to help you. The best way to get help is to provide information to enable other developers to understand the issue and reproduce it on their own machines.
Please create a new issue and fill out the entire issue template to the best of your ability. Refer to the following resources for more information on how to create a good issue report.
### Resources
- ["How do I ask a good question?"](https://stackoverflow.com/help/how-to-ask)
- ["How to create a Minimal, Reproducible Example"](https://stackoverflow.com/help/minimal-reproducible-example)
- ["How to narrow down the source of an error"](https://expo.fyi/manual-debugging)
`})
github.issues.update({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
state: 'closed'
})
issue-accepted:
runs-on: ubuntu-20.04
if: github.event.label.name == 'issue accepted'
steps:
- uses: actions/github-script@v3
with:
github-token: ${{ secrets.EXPO_BOT_GITHUB_TOKEN }}
script: |
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `Thank you for filing this issue!
This comment acknowledges we believe this may be a bug and there’s enough information to investigate it.
However, we can’t promise any sort of timeline for resolution. We prioritize issues based on severity, breadth of impact, and alignment with our roadmap. If you’d like to help move it more quickly, you can continue to investigate it more deeply and/or you can open a pull request that fixes the cause.
`})
question:
runs-on: ubuntu-20.04
if: "${{ contains(github.event.label.name, 'invalid issue: question') }}"
steps:
- uses: actions/github-script@v3
with:
github-token: ${{ secrets.EXPO_BOT_GITHUB_TOKEN }}
script: |
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `Hello! Our GitHub issues are reserved for bug reports.
If you have a question about Expo or related tools, please post on our forums at https://forums.expo.dev/ or join our Discord at https://chat.expo.dev/.
### Resources
- ["How do I ask a good question?"](https://stackoverflow.com/help/how-to-ask)
- ["Join the community"](https://docs.expo.dev/next-steps/community/)
`})
github.issues.update({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
state: 'closed'
})
feature-request:
runs-on: ubuntu-20.04
if: "${{ contains(github.event.label.name, 'invalid issue: feature request') }}"
steps:
- uses: actions/github-script@v3
with:
github-token: ${{ secrets.EXPO_BOT_GITHUB_TOKEN }}
script: |
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `Hello! Our GitHub issues are reserved for bug reports.
If you would like to request a feature, please post to https://expo.canny.io/feature-requests.
`})
github.issues.update({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
state: 'closed'
})
+5 -5
View File
@@ -27,7 +27,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
node-version: 18
- run: yarn install --frozen-lockfile --check-files
- run: yarn build
- name: Build tarballs
@@ -68,7 +68,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
node-version: 18
- run: yarn install --frozen-lockfile --check-files
- run: yarn build
- name: Build tarballs
@@ -96,7 +96,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
node-version: 18
- run: yarn install --frozen-lockfile --check-files
- run: sudo apt-get install nsis
- run: yarn build
@@ -138,7 +138,7 @@ jobs:
with:
registry-url: 'https://registry.npmjs.org/'
scope: 'expo'
node-version: '16'
node-version: 18
- name: Install dependencies
run: yarn install --frozen-lockfile --check-files
- name: Build
@@ -155,7 +155,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
node-version: 18
- name: Install dependencies
working-directory: ./scripts
run: yarn install --frozen-lockfile --check-files
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 16
node-version: 18
- uses: preactjs/compressed-size-action@v2
with:
build-script: 'build:tarballs:linux'
+26
View File
@@ -0,0 +1,26 @@
name: Test scripts
defaults:
run:
working-directory: scripts
on:
push:
branches: [main]
paths:
- 'scripts/**'
pull_request:
paths:
- 'scripts/**'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup node
uses: actions/setup-node@v2
with:
node-version: 18
- run: yarn install --frozen-lockfile --check-files
- run: yarn typecheck
+2 -2
View File
@@ -10,9 +10,9 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node: ['12', '14', '16']
node: ['14', '16', '18']
include:
- node: '16'
- node: '18'
coverage: true
name: Test with Node ${{ matrix.node }}
steps:
+5
View File
@@ -2,10 +2,12 @@
packages/*/build
packages/eas-cli/dist
packages/eas-cli/tmp
scripts/build
# Code editors
.idea
.history
.vscode
# macOS
.DS_Store
@@ -17,3 +19,6 @@ node_modules
# Tests
coverage
# Copies of script for testing ESM imports
packages/*/scripts/testESMImports.ts
+103 -2
View File
@@ -8,14 +8,115 @@ This is the log of notable changes to EAS CLI and related packages.
### 🎉 New features
- Show bundler output by default for eas update command. ([#1171](https://github.com/expo/eas-cli/pull/1171) by [@kgc00](https://github.com/kgc00/))
- Allow users to skip metadata validation. ([#1175](https://github.com/expo/eas-cli/pull/1175) by [@byCedric](https://github.com/byCedric))
- Add experimental `--resource-class` flag for Build commands. ([#1138](https://github.com/expo/eas-cli/pull/1138) by [@christopherwalter](https://github.com/christopherwalter))
- Truncate long messages for `eas update` command, rather than failing. ([#1178](https://github.com/expo/eas-cli/pull/1178) by [@kgc00](https://github.com/kgc00))
- Add review details to metadata store configuration. ([#1184](https://github.com/expo/eas-cli/pull/1184) by [@byCedric](https://github.com/byCedric))
### 🐛 Bug fixes
- Fix submission archive URLs. ([#1179](https://github.com/expo/eas-cli/pull/1179) by [@dsokal](https://github.com/dsokal))
### 🧹 Chores
- Update validation rules for metadata info locales. ([#1174](https://github.com/expo/eas-cli/pull/1174) by [@byCedric](https://github.com/byCedric))
- Improve store configuration defaults and schema documentation. ([#1183](https://github.com/expo/eas-cli/pull/1183) by [@byCedric](https://github.com/byCedric))
- Improve store config categories configuration. ([#1187](https://github.com/expo/eas-cli/pull/1187) by [@byCedric](https://github.com/byCedric))
- Remove deprecated idfa and price tier from store config. ([#1193](https://github.com/expo/eas-cli/pull/1193) by [@byCedric](https://github.com/byCedric))
## [0.54.1](https://github.com/expo/eas-cli/releases/tag/v0.54.1) - 2022-06-15
### 🎉 New features
- Add App Store Connect link after `eas metadata:push`. ([#1168](https://github.com/expo/eas-cli/pull/1168) by [@byCedric](https://github.com/byCedric))
### 🐛 Bug fixes
- Surface ASC errors in metadata for normal API rejections. ([#1167](https://github.com/expo/eas-cli/pull/1167) by [@byCedric](https://github.com/byCedric))
- Add metadata schema to bundled eas-cli package. ([#1166](https://github.com/expo/eas-cli/pull/1166) by [@byCedric](https://github.com/byCedric))
## [0.54.0](https://github.com/expo/eas-cli/releases/tag/v0.54.0) - 2022-06-15
### 🛠 Breaking changes
- Remove fallback for legacy format in `eas.json`. ([#1158](https://github.com/expo/eas-cli/pull/1158), [#1163](https://github.com/expo/eas-cli/pull/1163) by [@wkozyra95](https://github.com/wkozyra95))
### 🎉 New features
- `eas update` now provides more information about the publish process including real-time feedback on asset uploads, update ids, and website links. ([#1152](https://github.com/expo/eas-cli/pull/1152) by [@kgc00](https://github.com/kgc00/))
- Added first beta of `eas metadata` to sync store information using store configuration files ([#1136](https://github.com/expo/eas-cli/pull/1136) by [@bycedric](https://github.com/bycedric))
### 🐛 Bug fixes
- Improved support for working on branches with many updates. ([#1144](https://github.com/expo/eas-cli/pull/1144), [#1148](https://github.com/expo/eas-cli/pull/1148) by [@kgc00](https://github.com/kgc00/))
- `eas update` project links no longer contain a `)` on unsupported terminals. ([#1152](https://github.com/expo/eas-cli/pull/1152) by [@kgc00](https://github.com/kgc00/))
### 🧹 Chores
- Update `eas-build-job`. ([#1162](https://github.com/expo/eas-cli/pull/1162) by [@wkozyra95](https://github.com/wkozyra95))
## [0.53.1](https://github.com/expo/eas-cli/releases/tag/v0.53.1) - 2022-06-07
### 🐛 Bug fixes
- No longer timeout on publishing updates for branches with many updates. ([#1119](https://github.com/expo/eas-cli/pull/1119) by [@kgc00](https://github.com/kgc00/))
### 🧹 Chores
- Display project archive docs before compressing/uploading to EAS Build. ([#1127](https://github.com/expo/eas-cli/pull/1127) by [@dsokal](https://github.com/dsokal))
- Add new common error code for submits. ([#1129](https://github.com/expo/eas-cli/pull/1129) by [@dsokal](https://github.com/dsokal))
## [0.53.0](https://github.com/expo/eas-cli/releases/tag/v0.53.0) - 2022-05-30
### 🛠 Breaking changes
- Drop support for Node < 14. ([#1098](https://github.com/expo/eas-cli/pull/1098) by [@dsokal](https://github.com/dsokal))
### 🐛 Bug fixes
- Match bundle identifier capabilities more accurately. ([#1112](https://github.com/expo/eas-cli/pull/1112) by [@EvanBacon](https://github.com/EvanBacon))
- Limit concurrent asset uploads. ([#1153](https://github.com/expo/eas-cli/pull/1153) by [@wschurman](https://github.com/wschurman))
### 🧹 Chores
- Update dependencies. ([#1095](https://github.com/expo/eas-cli/pull/1095), [#1115](https://github.com/expo/eas-cli/pull/1115) by [@dsokal](https://github.com/dsokal))
- Better spinner placement for multiple builds. ([#1105](https://github.com/expo/eas-cli/pull/1105) by [@dsokal](https://github.com/dsokal))
- Use getExpoConfig to access config. ([#1122](https://github.com/expo/eas-cli/pull/1122) by [@wkozyra95](https://github.com/wkozyra95))
## [0.52.0](https://github.com/expo/eas-cli/releases/tag/v0.52.0) - 2022-04-26
### 🎉 New features
- Support target specific entitlements. ([#1078](https://github.com/expo/eas-cli/pull/1078) by [@wkozyra95](https://github.com/wkozyra95))
## [0.51.0](https://github.com/expo/eas-cli/releases/tag/v0.51.0) - 2022-04-19
### 🎉 New features
- Add non-interactive flag to eas update command. ([#1066](https://github.com/expo/eas-cli/pull/1066) by [@wschurman](https://github.com/wschurman))
- Handle new EAS Submit common error - expired Apple's certificates. ([#1068](https://github.com/expo/eas-cli/pull/1068) by [@dsokal](https://github.com/dsokal))
### 🐛 Bug fixes
- Enable full bundling logging for eas update when debugging. ([#1070](https://github.com/expo/eas-cli/pull/1070) by [@byCedric](https://github.com/byCedric))
### 🧹 Chores
- Upgrade `@expo/[email protected]` (now with license). ([#1064](https://github.com/expo/eas-cli/pull/1064) by [@EvanBacon](https://github.com/EvanBacon))
- Unify Google Service Account key prompts. ([#1063](https://github.com/expo/eas-cli/pull/1063) by [@dsokal](https://github.com/dsokal))
## [0.50.0](https://github.com/expo/eas-cli/releases/tag/v0.50.0) - 2022-04-11
### 🎉 New features
- Provide queue position progress and estimated wait time. ([#1049](https://github.com/expo/eas-cli/pull/1049), [#1058](https://github.com/expo/eas-cli/pull/1058) by [@dsokal](https://github.com/dsokal))
- Enable App Store authentication for ASC Api Keys with environment variables. ([#1051](https://github.com/expo/eas-cli/pull/1051) by [@quinlanj](https://github.com/quinlanj))
### 🐛 Bug fixes
- Prompt for user/password authentication where required. ([#1055](https://github.com/expo/eas-cli/pull/1055) by [@quinlanj](https://github.com/quinlanj))
### 🧹 Chores
- Require private-key-path to be specified for updating when code signing configured. ([#1059](https://github.com/expo/eas-cli/pull/1059) by [@wschurman](https://github.com/wschurman))
## [0.49.0](https://github.com/expo/eas-cli/releases/tag/v0.49.0) - 2022-04-05
+6
View File
@@ -1,7 +1,13 @@
* @dsokal @wkozyra95
packages/eas-cli/src/build @dsokal @wkozyra95
packages/eas-cli/src/commands/build @dsokal @wkozyra95
packages/eas-cli/src/submit @barthap @dsokal
packages/eas-cli/src/commands/submit.ts @barthap @dsokal
packages/eas-cli/schema @bycedric
packages/eas-cli/src/metadata @bycedric
packages/eas-cli/src/commands/metadata @bycedric
packages/eas-json @dsokal @wkozyra95
+7
View File
@@ -0,0 +1,7 @@
module.exports = {
projects: [
require('./packages/eas-cli/jest.config.cjs'),
require('./packages/eas-json/jest.config.cjs'),
],
testPathIgnorePatterns: ['.*'],
};
-7
View File
@@ -1,7 +0,0 @@
module.exports = {
projects: [
require('./packages/eas-cli/jest.config.js'),
require('./packages/eas-json/jest.config.js'),
],
testPathIgnorePatterns: ['.*'],
};
+9 -1
View File
@@ -1,7 +1,15 @@
module.exports = {
preset: 'ts-jest',
preset: 'ts-jest/presets/default-esm',
testEnvironment: 'node',
testRegex: '/__tests__/.*(test|spec)\\.[jt]sx?$',
watchPlugins: ['jest-watch-typeahead/filename', 'jest-watch-typeahead/testname'],
collectCoverageFrom: ['<rootDir>/src/**/*.{ts,tsx,js,jsx}'],
globals: {
'ts-jest': {
useESM: true,
},
},
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1',
},
};
+1 -1
View File
@@ -1,5 +1,5 @@
{
"npmClient": "yarn",
"useWorkspaces": true,
"version": "0.50.0"
"version": "0.54.1"
}
+16 -14
View File
@@ -1,5 +1,6 @@
{
"private": true,
"type": "module",
"workspaces": [
"packages/*"
],
@@ -13,26 +14,27 @@
"eas": "packages/eas-cli/bin/run",
"lint": "eslint .",
"release": "./scripts/bin/run update-local-plugin && lerna version --exact",
"test": "jest",
"clean": "lerna run clean && rm -rf node_modules coverage"
"test": "NODE_OPTIONS=--experimental-vm-modules jest",
"clean": "lerna run clean && rm -rf node_modules coverage",
"test-esm-imports": "lerna run test-esm-imports"
},
"devDependencies": {
"@types/jest": "27.4.1",
"@types/node": "16.7.8",
"eslint": "8.12.0",
"eslint-config-universe": "10.0.0",
"@types/jest": "27.5.0",
"@types/node": "17.0.32",
"eslint": "8.15.0",
"eslint-config-universe": "11.0.0",
"eslint-plugin-async-protect": "1.1.0",
"eslint-plugin-node": "11.1.0",
"jest": "27.5.1",
"jest-watch-typeahead": "1.0.0",
"jest": "28.1.0",
"jest-watch-typeahead": "1.1.0",
"lerna": "4.0.0",
"oclif": "2.6.3",
"prettier": "2.6.1",
"ts-jest": "27.1.4",
"typescript": "4.6.3"
"oclif": "3.0.1",
"prettier": "2.6.2",
"ts-jest": "28.0.2",
"typescript": "4.7.4"
},
"volta": {
"node": "16.10.0",
"yarn": "1.22.15"
"node": "18.2.0",
"yarn": "1.22.18"
}
}
@@ -1,4 +1,4 @@
const rootEslintrc = require('../../.eslintrc.js');
const rootEslintrc = require('../../.eslintrc.cjs');
module.exports = {
rules: {
+82 -45
View File
@@ -65,6 +65,8 @@ eas --help COMMAND
* [`eas init`](#eas-init)
* [`eas login`](#eas-login)
* [`eas logout`](#eas-logout)
* [`eas metadata:pull`](#eas-metadatapull)
* [`eas metadata:push`](#eas-metadatapush)
* [`eas project:info`](#eas-projectinfo)
* [`eas project:init`](#eas-projectinit)
* [`eas secret:create`](#eas-secretcreate)
@@ -98,7 +100,7 @@ ALIASES
$ eas login
```
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/account/login.ts)_
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/account/login.ts)_
## `eas account:logout`
@@ -115,7 +117,7 @@ ALIASES
$ eas logout
```
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/account/logout.ts)_
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/account/logout.ts)_
## `eas account:view`
@@ -132,7 +134,7 @@ ALIASES
$ eas whoami
```
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/account/view.ts)_
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/account/view.ts)_
## `eas analytics [STATUS]`
@@ -146,7 +148,7 @@ DESCRIPTION
display or change analytics settings
```
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/analytics.ts)_
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/analytics.ts)_
## `eas autocomplete [SHELL]`
@@ -175,7 +177,7 @@ EXAMPLES
$ eas autocomplete --refresh-cache
```
_See code: [@oclif/plugin-autocomplete](https://github.com/oclif/plugin-autocomplete/blob/v1.2.0/src/commands/autocomplete/index.ts)_
_See code: [@expo/plugin-autocomplete](https://github.com/expo/plugin-autocomplete/blob/v1.4.0/src/commands/autocomplete/index.ts)_
## `eas branch:create [NAME]`
@@ -195,7 +197,7 @@ DESCRIPTION
create a branch
```
_See code: [src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/branch/create.ts)_
_See code: [src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/branch/create.ts)_
## `eas branch:delete [NAME]`
@@ -215,7 +217,7 @@ DESCRIPTION
delete a branch
```
_See code: [src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/branch/delete.ts)_
_See code: [src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/branch/delete.ts)_
## `eas branch:list`
@@ -232,7 +234,7 @@ DESCRIPTION
list all branches
```
_See code: [src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/branch/list.ts)_
_See code: [src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/branch/list.ts)_
## `eas branch:rename`
@@ -251,7 +253,7 @@ DESCRIPTION
rename a branch
```
_See code: [src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/branch/rename.ts)_
_See code: [src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/branch/rename.ts)_
## `eas branch:view [NAME]`
@@ -271,7 +273,7 @@ DESCRIPTION
view a branch
```
_See code: [src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/branch/view.ts)_
_See code: [src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/branch/view.ts)_
## `eas build`
@@ -300,7 +302,7 @@ DESCRIPTION
start a build
```
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/build/index.ts)_
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/build/index.ts)_
## `eas build:cancel [BUILD_ID]`
@@ -314,7 +316,7 @@ DESCRIPTION
cancel a build
```
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/build/cancel.ts)_
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/build/cancel.ts)_
## `eas build:configure`
@@ -331,7 +333,7 @@ DESCRIPTION
configure the project to support EAS Build
```
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/build/configure.ts)_
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/build/configure.ts)_
## `eas build:inspect`
@@ -366,7 +368,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/v0.50.0/packages/eas-cli/src/commands/build/inspect.ts)_
_See code: [src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/build/inspect.ts)_
## `eas build:list`
@@ -399,7 +401,7 @@ DESCRIPTION
list all builds for your project
```
_See code: [src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/build/list.ts)_
_See code: [src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/build/list.ts)_
## `eas build:submit`
@@ -444,7 +446,7 @@ DESCRIPTION
view a build for your project
```
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/build/view.ts)_
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/build/view.ts)_
## `eas channel:create [NAME]`
@@ -464,7 +466,7 @@ DESCRIPTION
create a channel
```
_See code: [src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/channel/create.ts)_
_See code: [src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/channel/create.ts)_
## `eas channel:edit [NAME]`
@@ -485,7 +487,7 @@ DESCRIPTION
point a channel at a new branch
```
_See code: [src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/channel/edit.ts)_
_See code: [src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/channel/edit.ts)_
## `eas channel:list`
@@ -502,7 +504,7 @@ DESCRIPTION
list all channels
```
_See code: [src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/channel/list.ts)_
_See code: [src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/channel/list.ts)_
## `eas channel:view [NAME]`
@@ -522,7 +524,7 @@ DESCRIPTION
view a channel
```
_See code: [src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/channel/view.ts)_
_See code: [src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/channel/view.ts)_
## `eas config`
@@ -540,7 +542,7 @@ DESCRIPTION
display project configuration (app.json + eas.json)
```
_See code: [src/commands/config.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/config.ts)_
_See code: [src/commands/config.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/config.ts)_
## `eas credentials`
@@ -554,7 +556,7 @@ DESCRIPTION
manage credentials
```
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/credentials.ts)_
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/credentials.ts)_
## `eas device:create`
@@ -568,7 +570,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/v0.50.0/packages/eas-cli/src/commands/device/create.ts)_
_See code: [src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/device/create.ts)_
## `eas device:delete`
@@ -586,7 +588,7 @@ DESCRIPTION
remove a registered device from your account
```
_See code: [src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/device/delete.ts)_
_See code: [src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/device/delete.ts)_
## `eas device:list`
@@ -603,7 +605,7 @@ DESCRIPTION
list all registered devices for your account
```
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/device/list.ts)_
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/device/list.ts)_
## `eas device:view [UDID]`
@@ -617,7 +619,7 @@ DESCRIPTION
view a device for your project
```
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/device/view.ts)_
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/device/view.ts)_
## `eas diagnostics`
@@ -631,7 +633,7 @@ DESCRIPTION
display environment info
```
_See code: [src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/diagnostics.ts)_
_See code: [src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/diagnostics.ts)_
## `eas help [COMMAND]`
@@ -651,7 +653,7 @@ DESCRIPTION
Display help for eas.
```
_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v5.1.12/src/commands/help.ts)_
_See code: [@expo/plugin-help](https://github.com/expo/oclif-plugin-help/blob/v5.2.0/src/commands/help.ts)_
## `eas init`
@@ -698,6 +700,40 @@ ALIASES
$ eas logout
```
## `eas metadata:pull`
generate the local store configuration from the app stores
```
USAGE
$ eas metadata:pull [--profile <value>]
FLAGS
--profile=<value> Name of the submit profile from eas.json. Defaults to "production" if defined in eas.json.
DESCRIPTION
generate the local store configuration from the app stores
```
_See code: [src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/metadata/pull.ts)_
## `eas metadata:push`
sync the local store configuration to the app stores
```
USAGE
$ eas metadata:push [--profile <value>]
FLAGS
--profile=<value> Name of the submit profile from eas.json. Defaults to "production" if defined in eas.json.
DESCRIPTION
sync the local store configuration to the app stores
```
_See code: [src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/metadata/push.ts)_
## `eas project:info`
information about the current project
@@ -710,7 +746,7 @@ DESCRIPTION
information about the current project
```
_See code: [src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/project/info.ts)_
_See code: [src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/project/info.ts)_
## `eas project:init`
@@ -727,7 +763,7 @@ ALIASES
$ eas init
```
_See code: [src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/project/init.ts)_
_See code: [src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/project/init.ts)_
## `eas secret:create`
@@ -747,7 +783,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/v0.50.0/packages/eas-cli/src/commands/secret/create.ts)_
_See code: [src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/secret/create.ts)_
## `eas secret:delete`
@@ -764,7 +800,7 @@ DESCRIPTION
delete an environment secret by ID
```
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/secret/delete.ts)_
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/secret/delete.ts)_
## `eas secret:list`
@@ -778,7 +814,7 @@ DESCRIPTION
list environment secrets available for your current app
```
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/secret/list.ts)_
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/secret/list.ts)_
## `eas submit`
@@ -808,7 +844,7 @@ ALIASES
$ eas build:submit
```
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/submit.ts)_
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/submit.ts)_
## `eas update`
@@ -817,7 +853,7 @@ publish an update group
```
USAGE
$ eas update [--branch <value>] [--message <value>] [--republish | --input-dir <value> | --skip-bundler]
[--group <value> | | ] [-p android|ios|all] [--json] [--auto] [--private-key-path <value>]
[--group <value> | | ] [-p android|ios|all] [--json] [--auto] [--private-key-path <value>] [--non-interactive]
FLAGS
-p, --platform=(android|ios|all) [default: all]
@@ -827,6 +863,7 @@ FLAGS
--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
--non-interactive Run command in non-interactive mode
--private-key-path=<value> File containing the PEM-encoded private key corresponding to the certificate in
expo-updates' configuration. Defaults to a file named "private-key.pem" in the
certificate's directory.
@@ -837,7 +874,7 @@ DESCRIPTION
publish an update group
```
_See code: [src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/update/index.ts)_
_See code: [src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/update/index.ts)_
## `eas update:configure`
@@ -854,7 +891,7 @@ DESCRIPTION
configure the project to support EAS Update
```
_See code: [src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/update/configure.ts)_
_See code: [src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/update/configure.ts)_
## `eas update:delete GROUPID`
@@ -874,7 +911,7 @@ DESCRIPTION
delete all the updates in an update group
```
_See code: [src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/update/delete.ts)_
_See code: [src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/update/delete.ts)_
## `eas update:list`
@@ -893,7 +930,7 @@ DESCRIPTION
view the recent updates for a branch
```
_See code: [src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/update/list.ts)_
_See code: [src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/update/list.ts)_
## `eas update:view GROUPID`
@@ -913,7 +950,7 @@ DESCRIPTION
update group details
```
_See code: [src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/update/view.ts)_
_See code: [src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/update/view.ts)_
## `eas webhook:create`
@@ -933,7 +970,7 @@ DESCRIPTION
create a webhook
```
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/webhook/create.ts)_
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/webhook/create.ts)_
## `eas webhook:delete [ID]`
@@ -950,7 +987,7 @@ DESCRIPTION
delete a webhook
```
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/webhook/delete.ts)_
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/webhook/delete.ts)_
## `eas webhook:list`
@@ -967,7 +1004,7 @@ DESCRIPTION
list webhooks
```
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/webhook/list.ts)_
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/webhook/list.ts)_
## `eas webhook:update`
@@ -988,7 +1025,7 @@ DESCRIPTION
update a webhook
```
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/webhook/update.ts)_
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/webhook/update.ts)_
## `eas webhook:view ID`
@@ -1005,7 +1042,7 @@ DESCRIPTION
view a webhook
```
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v0.50.0/packages/eas-cli/src/commands/webhook/view.ts)_
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v0.54.1/packages/eas-cli/src/commands/webhook/view.ts)_
## `eas whoami`
-6
View File
@@ -1,6 +0,0 @@
#!/usr/bin/env node
require('@oclif/core')
.run()
.then(require('@oclif/core/flush'))
.catch(require('@oclif/core/handle'));
+7
View File
@@ -0,0 +1,7 @@
#!/usr/bin/env node
import { Errors, flush, run } from '@oclif/core';
run(undefined, import.meta.url)
.then(flush)
.catch(Errors.handle);
+781 -91
View File
File diff suppressed because it is too large. Load diff
@@ -1,5 +1,5 @@
module.exports = {
...require('../../jest/jest.config.js'),
...require('../../jest/jest.config.cjs'),
rootDir: __dirname,
roots: ['src', '__mocks__'],
globalSetup: './jest/global-setup.ts',
+2
View File
@@ -1,3 +1,5 @@
import { jest } from '@jest/globals';
/* eslint-disable no-console */
beforeAll(() => {
console.log = jest.fn();
+56 -41
View File
@@ -1,38 +1,40 @@
{
"name": "eas-cli",
"type": "module",
"description": "EAS command line tool",
"version": "0.50.0",
"version": "0.54.1",
"author": "Expo <[email protected]>",
"bin": {
"eas": "./bin/run"
},
"bugs": "https://github.com/expo/eas-cli/issues",
"dependencies": {
"@expo/apple-utils": "0.0.0-alpha.30",
"@expo/apple-utils": "0.0.0-alpha.33",
"@expo/code-signing-certificates": "0.0.2",
"@expo/config": "6.0.19",
"@expo/config-plugins": "4.1.0",
"@expo/config-types": "44.0.0",
"@expo/eas-build-job": "0.2.68",
"@expo/eas-json": "0.50.0",
"@expo/json-file": "8.2.34",
"@expo/config": "6.0.23",
"@expo/config-plugins": "4.1.4",
"@expo/config-types": "45.0.0",
"@expo/eas-build-job": "0.2.77",
"@expo/eas-json": "0.54.0",
"@expo/json-file": "8.2.36",
"@expo/multipart-body-parser": "1.1.0",
"@expo/pkcs12": "0.0.7",
"@expo/plist": "0.0.17",
"@expo/plugin-warn-if-update-available": "2.1.0",
"@expo/prebuild-config": "3.1.0",
"@expo/pkcs12": "0.0.8",
"@expo/plist": "0.0.18",
"@expo/plugin-autocomplete": "1.4.0",
"@expo/plugin-help": "5.2.0",
"@expo/plugin-warn-if-update-available": "2.3.0",
"@expo/prebuild-config": "3.1.6",
"@expo/results": "1.0.0",
"@expo/rudder-sdk-node": "1.1.1",
"@expo/spawn-async": "1.6.0",
"@expo/timeago.js": "1.0.0",
"@oclif/core": "1.6.4",
"@oclif/plugin-autocomplete": "1.2.0",
"@oclif/plugin-help": "5.1.12",
"@urql/core": "2.4.3",
"@urql/exchange-retry": "0.3.2",
"@oclif/core": "1.9.5",
"@urql/core": "2.4.4",
"@urql/exchange-retry": "0.3.3",
"ajv": "^6.12.6",
"chalk": "4.1.2",
"cli-progress": "3.10.0",
"cli-table3": "0.6.1",
"cli-progress": "3.11.0",
"cli-table3": "0.6.2",
"dateformat": "4.6.3",
"env-paths": "2.2.0",
"envinfo": "7.8.1",
@@ -40,12 +42,12 @@
"fast-glob": "3.2.11",
"figures": "3.2.0",
"form-data": "4.0.0",
"fs-extra": "10.0.1",
"fs-extra": "10.1.0",
"getenv": "1.0.0",
"gradle-to-js": "2.0.0",
"graphql": "16.3.0",
"gradle-to-js": "2.0.1",
"graphql": "16.5.0",
"graphql-tag": "2.12.6",
"https-proxy-agent": "5.0.0",
"https-proxy-agent": "5.0.1",
"ignore": "5.2.0",
"indent-string": "4.0.0",
"jks-js": "1.0.2",
@@ -53,22 +55,23 @@
"keychain": "1.3.0",
"log-symbols": "4.1.0",
"mime": "3.0.0",
"minimatch": "3.0.5",
"nanoid": "3.3.2",
"minimatch": "5.0.1",
"nanoid": "3.3.4",
"node-fetch": "2.6.7",
"node-forge": "1.3.1",
"nullthrows": "1.1.1",
"ora": "5.1.0",
"pkg-dir": "4.2.0",
"promise-limit": "2.7.0",
"prompts": "2.4.2",
"qrcode-terminal": "0.12.0",
"resolve-from": "5.0.0",
"semver": "7.3.5",
"semver": "7.3.7",
"slash": "3.0.0",
"strip-ansi": "6.0.0",
"tar": "6.1.11",
"terminal-link": "2.1.1",
"tslib": "2.3.1",
"tslib": "2.4.0",
"turndown": "7.1.1",
"untildify": "4.0.0",
"uuid": "8.3.2",
@@ -77,8 +80,9 @@
"devDependencies": {
"@graphql-codegen/cli": "2.6.2",
"@graphql-codegen/introspection": "2.1.1",
"@graphql-codegen/typescript": "2.4.8",
"@graphql-codegen/typescript-operations": "2.3.5",
"@graphql-codegen/typescript": "2.4.11",
"@graphql-codegen/typescript-operations": "2.4.0",
"@jest/globals": "28.1.2",
"@types/cli-progress": "3.9.2",
"@types/dateformat": "3.0.1",
"@types/envinfo": "7.8.1",
@@ -86,30 +90,33 @@
"@types/getenv": "^1.0.0",
"@types/mime": "2.0.3",
"@types/node-fetch": "^2.5.7",
"@types/node-forge": "1.0.1",
"@types/node-forge": "1.0.2",
"@types/prompts": "2.0.14",
"@types/semver": "7.3.9",
"@types/tar": "6.1.1",
"@types/tough-cookie": "4.0.1",
"@types/tough-cookie": "4.0.2",
"@types/uuid": "8.3.4",
"@types/wrap-ansi": "3.0.0",
"axios": "0.26.1",
"axios": "0.27.2",
"eslint-plugin-graphql": "4.0.0",
"form-data": "4.0.0",
"memfs": "3.4.1",
"globby": "13.1.2",
"memfs": "3.4.3",
"mockdate": "3.0.5",
"nock": "13.2.4",
"tempy": "0.7.0",
"ts-deepmerge": "2.0.1",
"typescript": "4.6.3"
"ts-node": "10.8.2",
"typescript": "4.7.4"
},
"engines": {
"node": ">=12.0.0"
"node": ">=14.16"
},
"files": [
"/bin",
"/build",
"/oclif.manifest.json"
"/oclif.manifest.json",
"/schema"
],
"homepage": "https://github.com/expo/eas-cli",
"keywords": [
@@ -122,8 +129,8 @@
"bin": "eas",
"commands": "./build/commands",
"plugins": [
"@oclif/plugin-autocomplete",
"@oclif/plugin-help",
"@expo/plugin-autocomplete",
"@expo/plugin-help",
"@expo/plugin-warn-if-update-available"
],
"topics": {
@@ -142,6 +149,9 @@
"device": {
"description": "manage Apple devices for Internal Distribution"
},
"metadata": {
"description": "manage store configuration"
},
"project": {
"description": "manage project"
},
@@ -190,9 +200,14 @@
"build": "tsc --project tsconfig.build.json",
"watch": "yarn build --watch --preserveWatchOutput",
"typecheck": "tsc",
"test": "jest",
"version": "yarn oclif readme && node scripts/patch-readme && git add README.md",
"test": "NODE_OPTIONS=--experimental-vm-modules jest",
"version": "yarn oclif readme && node scripts/patch-readme.cjs && git add README.md",
"generate-graphql-code": "graphql-codegen --config graphql-codegen.yml",
"clean": "rm -rf dist build tmp node_modules yarn-error.log"
"clean": "rm -rf dist build tmp node_modules yarn-error.log",
"test-esm-imports": "cp ../../scripts/src/testESMImports.ts scripts/ && ts-node-esm ./scripts/testESMImports.ts 'build/**/*.js'"
},
"volta": {
"node": "18.2.0",
"yarn": "1.22.18"
}
}
+988
View File
@@ -0,0 +1,988 @@
{
"$schema": "http://json-schema.org/draft-06/schema",
"type": "object",
"definitions": {
"apple": {
"AppleLocalizedPreviewFolder": {
"anyOf": [
{
"description": "Path to folder containing preview files",
"type": "string"
},
{
"type": "array",
"uniqueItems": true,
"items": {
"type": "string"
}
}
]
},
"AppleKidsAge": {
"enum": [
"FIVE_AND_UNDER",
"SIX_TO_EIGHT",
"NINE_TO_ELEVEN"
]
},
"AppleRating": {
"enum": [
"NONE",
"INFREQUENT_OR_MILD",
"FREQUENT_OR_INTENSE"
]
},
"AppleCategory": {
"type": "array",
"description": "App Store categories for the app, can add up to two categories. The first item in this list is the primary category, the second is the secondary and optional category. `STICKERS` and `GAMES` categories can add up to two additional subcategories, written as nested array.",
"markdownDescription": "App Store categories for the app, can add up to two categories. The first item in this list is the primary category, the second is the secondary and optional category. `STICKERS` and `GAMES` categories can add up to two additional subcategories, written as nested array. E.g.\n\n- `[\"SPORTS\"]`\n- `[\"SPORTS\", \"LIFESTYLE\"]`\n- `[[\"GAMES\", \"GAMES_CARD\"], \"ENTERTAINMENT\"]`\n- `[\"GAMES\", \"WEATHER\"]`",
"minItems": 1,
"maxItems": 2,
"uniqueItems": true,
"defaultSnippets": [
{
"label": "Basic categories",
"description": "Add two simple categories",
"body": [
"$1",
"$2"
]
},
{
"label": "Category with subcategories",
"description": "Add a category containing subcategories",
"body": [
[
"${1|GAMES,STICKERS|}",
"$3",
"$4"
]
]
}
],
"items": {
"oneOf": [
{
"$ref": "#/definitions/apple/AppleCategory/categories/root"
},
{
"$ref": "#/definitions/apple/AppleCategory/categories/parent"
},
{
"type": "array",
"description": "The GAMES category can have additional subcategories",
"minItems": 1,
"maxItems": 3,
"uniqueItems": true,
"items": [
{
"const": "GAMES"
},
{
"$ref": "#/definitions/apple/AppleCategory/categories/games"
},
{
"$ref": "#/definitions/apple/AppleCategory/categories/games"
}
]
},
{
"type": "array",
"description": "The STICKERS category can have additional subcategories",
"minItems": 1,
"maxItems": 3,
"uniqueItems": true,
"items": [
{
"const": "STICKERS"
},
{
"$ref": "#/definitions/apple/AppleCategory/categories/stickers"
},
{
"$ref": "#/definitions/apple/AppleCategory/categories/stickers"
}
]
}
]
},
"categories": {
"root": {
"enum": [
"BUSINESS",
"SOCIAL_NETWORKING",
"MEDICAL",
"FOOD_AND_DRINK",
"EDUCATION",
"BOOKS",
"SPORTS",
"FINANCE",
"REFERENCE",
"GRAPHICS_AND_DESIGN",
"DEVELOPER_TOOLS",
"HEALTH_AND_FITNESS",
"MUSIC",
"WEATHER",
"TRAVEL",
"ENTERTAINMENT",
"LIFESTYLE",
"MAGAZINES_AND_NEWSPAPERS",
"UTILITIES",
"SHOPPING",
"PRODUCTIVITY",
"NEWS",
"PHOTO_AND_VIDEO",
"NAVIGATION"
]
},
"parent": {
"enum": [
"GAMES",
"STICKERS"
]
},
"games": {
"enum": [
"GAMES_SPORTS",
"GAMES_WORD",
"GAMES_MUSIC",
"GAMES_ADVENTURE",
"GAMES_ACTION",
"GAMES_ROLE_PLAYING",
"GAMES_CASUAL",
"GAMES_BOARD",
"GAMES_TRIVIA",
"GAMES_CARD",
"GAMES_PUZZLE",
"GAMES_CASINO",
"GAMES_STRATEGY",
"GAMES_SIMULATION",
"GAMES_RACING",
"GAMES_FAMILY"
]
},
"stickers": {
"enum": [
"STICKERS_PLACES_AND_OBJECTS",
"STICKERS_EMOJI_AND_EXPRESSIONS",
"STICKERS_CELEBRATIONS",
"STICKERS_CELEBRITIES",
"STICKERS_MOVIES_AND_TV",
"STICKERS_SPORTS_AND_ACTIVITIES",
"STICKERS_EATING_AND_DRINKING",
"STICKERS_CHARACTERS",
"STICKERS_ANIMALS",
"STICKERS_FASHION",
"STICKERS_ART",
"STICKERS_GAMING",
"STICKERS_KIDS_AND_FAMILY",
"STICKERS_PEOPLE",
"STICKERS_MUSIC"
]
}
}
},
"AppleInfo": {
"type": "object",
"additionalProperties": false,
"required": [
"title",
"privacyPolicyUrl"
],
"defaultSnippets": [
{
"label": "Basic",
"description": "Create the minimum required locale properties",
"body": {
"title": "${1:App title}",
"privacyPolicyUrl": "https://${3:www.}"
}
},
{
"label": "Full",
"description": "Create all available locale properties",
"body": {
"title": "${1:App title}",
"subtitle": "${2:Subtitle for your app}",
"description": "${3:A longer description of what your app does}",
"keywords": [
"${4:keyword}"
],
"releaseNotes": "${5:Bug fixes and improved stability}",
"promoText": "${6:Short tagline for your app}",
"marketingUrl": "https://${7:www.}",
"supportUrl": "https://${8:www.}",
"privacyPolicyUrl": "https://${9:www.}",
"privacyChoicesUrl": "https://${10:www.}"
}
}
],
"properties": {
"title": {
"type": "string",
"description": "Name of the app in the store. This should be similar to the installed app name.",
"minLength": 2,
"maxLength": 30,
"meta": {
"storeInfo": "The name will be reviewed before it is made available on the App Store."
}
},
"subtitle": {
"type": "string",
"description": "Subtext for the app. Example: 'A Fun Game For Friends'",
"maxLength": 30,
"meta": {
"storeInfo": "The subtitle will be reviewed before it is made available on the App Store."
}
},
"description": {
"type": "string",
"description": "Main description of what the app does",
"minLength": 10,
"maxLength": 4000,
"meta": {
"versioned": true,
"liveEdits": true
}
},
"keywords": {
"type": "array",
"description": "List of keywords to help users find the app in the App Store",
"uniqueItems": true,
"items": {
"maxLength": 100,
"type": "string"
},
"meta": {
"versioned": true
}
},
"releaseNotes": {
"type": "string",
"description": "Changes since the last public version",
"maxLength": 4000,
"meta": {
"versioned": true,
"liveEdits": true
}
},
"promoText": {
"type": "string",
"description": "Short tagline for the app",
"maxLength": 170,
"meta": {
"versioned": true,
"liveEdits": true,
"aso": false
}
},
"marketingUrl": {
"type": "string",
"description": "URL to the app marketing page",
"maxLength": 255,
"meta": {
"versioned": true,
"liveEdits": true
}
},
"supportUrl": {
"type": "string",
"description": "URL to the app support page",
"maxLength": 255,
"meta": {
"versioned": true,
"liveEdits": true
}
},
"privacyPolicyText": {
"type": "string",
"description": "Privacy policy for Apple TV"
},
"privacyPolicyUrl": {
"type": "string",
"description": "A URL that links to your privacy policy. A privacy policy is required for all apps.",
"maxLength": 255,
"meta": {
"versioned": true,
"liveEdits": true
}
},
"privacyChoicesUrl": {
"type": "string",
"description": "A URL where users can modify and delete the data collected from the app, or decide how their data is used and shared.",
"maxLength": 255,
"meta": {
"versioned": true,
"liveEdits": true,
"optional": true
}
}
}
},
"AppleAdvisory": {
"type": "object",
"additionalProperties": false,
"required": [
"alcoholTobaccoOrDrugUseOrReferences",
"contests",
"gamblingSimulated",
"horrorOrFearThemes",
"matureOrSuggestiveThemes",
"medicalOrTreatmentInformation",
"profanityOrCrudeHumor",
"sexualContentGraphicAndNudity",
"sexualContentOrNudity",
"violenceCartoonOrFantasy",
"violenceRealistic",
"violenceRealisticProlongedGraphicOrSadistic",
"gambling",
"unrestrictedWebAccess",
"kidsAgeBand",
"seventeenPlus"
],
"defaultSnippets": [
{
"label": "Basic",
"description": "Create an advisory that disables all age-rated properties, for when your app does nothing",
"body": {
"alcoholTobaccoOrDrugUseOrReferences": "NONE",
"contests": "NONE",
"gamblingSimulated": "NONE",
"horrorOrFearThemes": "NONE",
"matureOrSuggestiveThemes": "NONE",
"medicalOrTreatmentInformation": "NONE",
"profanityOrCrudeHumor": "NONE",
"sexualContentGraphicAndNudity": "NONE",
"sexualContentOrNudity": "NONE",
"violenceCartoonOrFantasy": "NONE",
"violenceRealistic": "NONE",
"violenceRealisticProlongedGraphicOrSadistic": "NONE",
"gambling": false,
"unrestrictedWebAccess": false,
"kidsAgeBand": null,
"seventeenPlus": false
}
},
{
"label": "Full",
"description": "Create an advisory that enables some of the age-rated properties",
"body": {
"alcoholTobaccoOrDrugUseOrReferences": "${1|NONE,INFREQUENT_OR_MILD,FREQUENT_OR_INTENSE|}",
"contests": "${2|NONE,INFREQUENT_OR_MILD,FREQUENT_OR_INTENSE|}",
"gamblingSimulated": "${3|NONE,INFREQUENT_OR_MILD,FREQUENT_OR_INTENSE|}",
"horrorOrFearThemes": "${4|NONE,INFREQUENT_OR_MILD,FREQUENT_OR_INTENSE|}",
"matureOrSuggestiveThemes": "${5|NONE,INFREQUENT_OR_MILD,FREQUENT_OR_INTENSE|}",
"medicalOrTreatmentInformation": "${6|NONE,INFREQUENT_OR_MILD,FREQUENT_OR_INTENSE|}",
"profanityOrCrudeHumor": "${7|NONE,INFREQUENT_OR_MILD,FREQUENT_OR_INTENSE|}",
"sexualContentGraphicAndNudity": "${8|NONE,INFREQUENT_OR_MILD,FREQUENT_OR_INTENSE|}",
"sexualContentOrNudity": "${9|NONE,INFREQUENT_OR_MILD,FREQUENT_OR_INTENSE|}",
"violenceCartoonOrFantasy": "${10|NONE,INFREQUENT_OR_MILD,FREQUENT_OR_INTENSE|}",
"violenceRealistic": "${11|NONE,INFREQUENT_OR_MILD,FREQUENT_OR_INTENSE|}",
"violenceRealisticProlongedGraphicOrSadistic": "${12|NONE,INFREQUENT_OR_MILD,FREQUENT_OR_INTENSE|}",
"unrestrictedWebAccess": false,
"gambling": false,
"kidsAgeBand": null,
"seventeenPlus": false
}
}
],
"properties": {
"alcoholTobaccoOrDrugUseOrReferences": {
"$ref": "#/definitions/apple/AppleRating",
"description": "Does the app contain alcohol, tobacco, or drug use or references?"
},
"contests": {
"$ref": "#/definitions/apple/AppleRating",
"description": "Does the app contain contests?"
},
"gamblingSimulated": {
"$ref": "#/definitions/apple/AppleRating",
"description": "Does the app contain simulated gambling?"
},
"medicalOrTreatmentInformation": {
"$ref": "#/definitions/apple/AppleRating",
"description": "Does the app contain medical or treatment information?"
},
"profanityOrCrudeHumor": {
"$ref": "#/definitions/apple/AppleRating",
"description": "Does the app contain profanity or crude humor?"
},
"sexualContentGraphicAndNudity": {
"$ref": "#/definitions/apple/AppleRating",
"description": "Does the app contain graphic sexual content and nudity?"
},
"sexualContentOrNudity": {
"$ref": "#/definitions/apple/AppleRating",
"description": "Does the app contain sexual content or nudity?"
},
"horrorOrFearThemes": {
"$ref": "#/definitions/apple/AppleRating",
"description": "Does the app contain horror or fear themes?"
},
"matureOrSuggestiveThemes": {
"$ref": "#/definitions/apple/AppleRating",
"description": "Does the app contain mature or suggestive themes?"
},
"violenceCartoonOrFantasy": {
"$ref": "#/definitions/apple/AppleRating",
"description": "Does the app contain cartoon or fantasy violence?"
},
"violenceRealisticProlongedGraphicOrSadistic": {
"$ref": "#/definitions/apple/AppleRating",
"description": "Does the app contain prolonged graphic or sadistic realistic violence?"
},
"violenceRealistic": {
"$ref": "#/definitions/apple/AppleRating",
"description": "Does the app contain realistic violence?"
},
"unrestrictedWebAccess": {
"type": "boolean",
"description": "Does your app contain unrestricted web access, such as with an embedded browser?"
},
"gambling": {
"type": "boolean",
"description": "Does your app contain gambling?"
},
"kidsAgeBand": {
"oneOf": [
{
"type": "null"
},
{
"$ref": "#/definitions/apple/AppleKidsAge"
}
],
"description": "When parents visit the Kids category on the App Store, they expect the apps they find will protect their children’s data, provide only age-appropriate content, and require a parental gate in order to link out of the app, request permissions, or present purchasing opportunities. It’s critical that no personally identifiable information or device information be transmitted to third parties, and that advertisements are human-reviewed for age appropriateness in order to be displayed.\n@see https://developer.apple.com/news/?id=091202019a",
"markdownDescription": "When parents visit the Kids category on the App Store, they expect the apps they find will protect their children’s data, provide only age-appropriate content, and require a parental gate in order to link out of the app, request permissions, or present purchasing opportunities. It’s critical that no personally identifiable information or device information be transmitted to third parties, and that advertisements are human-reviewed for age appropriateness in order to be displayed.\n\n[Learn more](https://developer.apple.com/news/?id=091202019a)"
},
"seventeenPlus": {
"type": "boolean",
"description": "If your app rates 12+ or lower, and you believe its content may not be suitable for children under 17, you can manually set the age rating to 17+.\n@see https://help.apple.com/app-store-connect/#/dev599d50efb",
"markdownDescription": "If your app rates 12+ or lower, and you believe its content may not be suitable for children under 17, you can manually set the age rating to 17+.\n\n[Learn more](https://help.apple.com/app-store-connect/#/dev599d50efb)"
}
}
},
"AppleRelease": {
"type": "object",
"additionalProperties": false,
"defaultSnippets": [
{
"body": {
"automaticRelease": true,
"usesThirdPartyContent": false,
"usesNonExemptEncryption": false
}
}
],
"properties": {
"autoReleaseDate": {
"description": "ISO Date to release the app automatically. Leave undefined to manually release the app to the public.",
"defaultSnippets": [
{
"body": "$CURRENT_YEAR-${1:$CURRENT_MONTH}-${2:$CURRENT_DATE}"
}
],
"anyOf": [
{
"type": "string",
"format": "date-time"
},
{
"type": "string",
"format": "date"
},
{
"type": "number"
}
]
},
"isPhasedReleaseEnabled": {
"type": "boolean",
"description": "Release update over 7-day period instead of instantly.",
"meta": {
"storeInfo": "Phased release for automatic updates lets you gradually release this update over a 7-day period to users who have turned on automatic updates. Keep in mind that this version will still be available to all users as a manual update from the App Store. You can pause the phased release for up to 30 days or release this update to all users at any time. [Learn More](https://help.apple.com/app-store-connect/#/dev3d65fcee1)."
}
},
"shouldResetRatings": {
"type": "boolean",
"description": "Should App Store ratings be reset for this version of the app.",
"meta": {
"storeInfo": "You can reset your app’s summary rating for all countries or regions when you release this version. Keep in mind that once this version is released, you won’t be able to restore the rating. Your app’s existing customer reviews will still appear on the App Store."
}
},
"usesThirdPartyContent": {
"type": "boolean"
},
"automaticRelease": {
"type": "boolean",
"description": "Should the app automatically be released when approved by App Store review."
},
"usesNonExemptEncryption": {
"type": "boolean",
"description": "Alternative to setting `ITSAppUsesNonExemptEncryption` in the binary's `Info.plist`."
}
}
},
"AppleReview": {
"type": "object",
"description": "Info provided to the App Store review team to help them understand how to use your app.",
"required": [
"firstName",
"lastName",
"email",
"phone"
],
"defaultSnippets": [
{
"label": "Basic",
"description": "Only define the contact details in case communcation is needed with the App Store review team.",
"body": {
"firstName": "$1",
"lastName": "$2",
"email": "$3",
"phone": "+$4"
}
},
{
"label": "Full",
"description": "Define the demo account credentials, additional info, and contact details for the App Store review team.",
"body": {
"firstName": "$1",
"lastName": "$2",
"email": "$3",
"phone": "+$4",
"demoUsername": "$5",
"demoPassword": "$6",
"demoRequired": true,
"notes": "$7"
}
}
],
"properties": {
"firstName": {
"type": "string",
"description": "First name of contact in case communication is needed with the App Store review team.",
"minLength": 1
},
"lastName": {
"type": "string",
"description": "Last name of contact in case communication is needed with the App Store review team.",
"minLength": 1
},
"email": {
"type": "string",
"description": "Email address of contact in case communication is needed with the App Store review team.",
"format": "email"
},
"phone": {
"type": "string",
"description": "Phone number of contact in case communication is needed with the App Store review team. Preface the phone number with ‘+’ followed by the country code (for example, +44 844 209 0611)"
},
"demoUsername": {
"type": "string",
"description": "The user name to sign in to your app to review its features."
},
"demoPassword": {
"type": "string",
"description": "The password to sign in to your app to review its features."
},
"demoRequired": {
"type": "boolean",
"description": "A Boolean value that indicates if sign-in information is required to review all the features of your app. If users sign in using social media, provide information for an account for review. Credentials must be valid and active for duration of review.",
"markdownDescription": "A Boolean value that indicates if sign-in information is required to review all the features of your app. If users sign in using social media, provide information for an account for review.\n\n**Credentials must be valid and active for duration of review.**"
},
"notes": {
"type": "string",
"description": "Additional information about your app that can help during the review process. Do not include demo account details.",
"markdownDescription": "Additional information about your app that can help during the review process.\n\n**Do not include demo account details.**",
"minLength": 2,
"maxLength": 4000
}
}
}
},
"AppleConfig": {
"type": "object",
"description": "Configuration that is specific to the Apple App Store.",
"additionalProperties": false,
"properties": {
"advisory": {
"$ref": "#/definitions/apple/AppleAdvisory"
},
"categories": {
"$ref": "#/definitions/apple/AppleCategory"
},
"copyright": {
"type": "string",
"description": "The updated company copyright. Example: 2021 Evan Bacon",
"defaultSnippets": [
{
"body": "$CURRENT_YEAR ${1:name}"
}
],
"meta": {
"versioned": true,
"liveEdits": true,
"storeInfo": "The name of the person or entity that owns the exclusive rights to your app, preceded by the year the rights were obtained (for example, \"2008 Acme Inc.\"). Do not provide a URL."
}
},
"info": {
"description": "Localized core app info",
"type": "object",
"additionalProperties": false,
"properties": {
"ar-SA": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Arabic"
},
"ca": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Catalan"
},
"zh-Hans": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Chinese (Simplified)"
},
"zh-Hant": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Chinese (Traditional)"
},
"hr": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Croatian"
},
"cs": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Czech"
},
"da": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Danish"
},
"nl-NL": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Dutch"
},
"en-AU": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "English (Australia)"
},
"en-CA": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "English (Canada)"
},
"en-GB": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "English (U.K.)"
},
"en-US": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "English (U.S.)"
},
"fi": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Finnish"
},
"fr-FR": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "French"
},
"fr-CA": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "French (Canada)"
},
"de-DE": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "German"
},
"el": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Greek"
},
"he": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Hebrew"
},
"hi": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Hindi"
},
"hu": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Hungarian"
},
"id": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Indonesian"
},
"it": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Italian"
},
"ja": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Japanese"
},
"ko": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Korean"
},
"ms": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Malay"
},
"no": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Norwegian"
},
"pl": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Polish"
},
"pt-BR": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Portuguese (Brazil)"
},
"pt-PT": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Portuguese (Portugal)"
},
"ro": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Romanian"
},
"ru": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Russian"
},
"sk": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Slovak"
},
"es-MX": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Spanish (Mexico)"
},
"es-ES": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Spanish (Spain)"
},
"sv": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Swedish"
},
"th": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Thai"
},
"tr": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Turkish"
},
"uk": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Ukrainian"
},
"vi": {
"$ref": "#/definitions/apple/AppleInfo",
"description": "Vietnamese"
}
}
},
"preview": {
"anyOf": [
{
"description": "Path to localized folders containing preview files",
"type": "string"
},
{
"description": "Localized previews object. Ex: `\"en-US\": [\"image.png\"]`",
"type": "object",
"additionalProperties": false,
"properties": {
"ar-SA": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Arabic"
},
"ca": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Catalan"
},
"zh-Hans": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Chinese (Simplified)"
},
"zh-Hant": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Chinese (Traditional)"
},
"hr": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Croatian"
},
"cs": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Czech"
},
"da": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Danish"
},
"nl-NL": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Dutch"
},
"en-AU": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "English (Australia)"
},
"en-CA": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "English (Canada)"
},
"en-GB": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "English (U.K.)"
},
"en-US": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "English (U.S.)"
},
"fi": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Finnish"
},
"fr-FR": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "French"
},
"fr-CA": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "French (Canada)"
},
"de-DE": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "German"
},
"el": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Greek"
},
"he": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Hebrew"
},
"hi": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Hindi"
},
"hu": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Hungarian"
},
"id": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Indonesian"
},
"it": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Italian"
},
"ja": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Japanese"
},
"ko": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Korean"
},
"ms": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Malay"
},
"no": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Norwegian"
},
"pl": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Polish"
},
"pt-BR": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Portuguese (Brazil)"
},
"pt-PT": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Portuguese (Portugal)"
},
"ro": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Romanian"
},
"ru": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Russian"
},
"sk": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Slovak"
},
"es-MX": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Spanish (Mexico)"
},
"es-ES": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Spanish (Spain)"
},
"sv": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Swedish"
},
"th": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Thai"
},
"tr": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Turkish"
},
"uk": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Ukrainian"
},
"vi": {
"$ref": "#/definitions/apple/AppleLocalizedPreviewFolder",
"description": "Vietnamese"
}
}
}
]
},
"release": {
"$ref": "#/definitions/apple/AppleRelease",
"description": "Release strategy"
},
"review": {
"$ref": "#/definitions/apple/AppleReview",
"description": "Info for the App Store reviewer"
}
}
}
},
"properties": {
"configVersion": {
"const": 0,
"description": "The EAS metadata store configuration version"
},
"apple": {
"$ref": "#/definitions/AppleConfig"
}
},
"additionalProperties": false,
"required": [
"configVersion",
"apple"
]
}
+1 -1
View File
@@ -1,7 +1,7 @@
import assert from 'assert';
import nock from 'nock';
import { ApiV2Error, api, getExpoApiBaseUrl } from '../api';
import { ApiV2Error, api, getExpoApiBaseUrl } from '../api.js';
describe('apiClient', () => {
it('converts Expo APIv2 error to ApiV2Error', async () => {
@@ -1,4 +1,4 @@
import { Actor } from '../user/User';
import { Actor } from '../user/User.js';
interface MockProject {
projectRoot: string;
@@ -0,0 +1,17 @@
import { fixArchiveUrl } from '../uploads.js';
describe(fixArchiveUrl, () => {
it('fixes broken links', () => {
const input =
'https://submission-service-archives.s3.amazonaws.com/production%2Fdc98ca84-1473-4cb3-ae81-8c7b291cb27e%2F4424aa95-b985-4e2f-8755-9507b1037c1c';
const expectedOutput =
'https://submission-service-archives.s3.amazonaws.com/production/dc98ca84-1473-4cb3-ae81-8c7b291cb27e/4424aa95-b985-4e2f-8755-9507b1037c1c';
expect(fixArchiveUrl(input)).toBe(expectedOutput);
});
it('does not change correct urls', () => {
const correctUrl =
'https://submission-service-archives.s3.amazonaws.com/production/dc98ca84-1473-4cb3-ae81-8c7b291cb27e/4424aa95-b985-4e2f-8755-9507b1037c1c';
expect(fixArchiveUrl(correctUrl)).toBe(correctUrl);
});
});
-3
View File
@@ -1,3 +0,0 @@
export function asMock(fn: any): jest.Mock {
return fn as jest.Mock;
}
+1 -1
View File
@@ -1,4 +1,4 @@
import { Analytics, Event } from './events';
import { Analytics, Event } from './events.js';
export type TrackingContext = Record<string, string | number | boolean>;
+7 -2
View File
@@ -1,5 +1,5 @@
import { logEvent } from './rudderstackClient';
export type Event = BuildEvent | SubmissionEvent;
import { logEvent } from './rudderstackClient.js';
export type Event = BuildEvent | SubmissionEvent | MetadataEvent;
export enum SubmissionEvent {
SUBMIT_COMMAND = 'submit cli submit command',
@@ -45,6 +45,11 @@ export enum BuildEvent {
ANDROID_KEYSTORE_CREATE = 'build cli credentials keystore create',
}
export enum MetadataEvent {
APPLE_METADATA_DOWNLOAD = 'metadata cli download apple response',
APPLE_METADATA_UPLOAD = 'metadata cli upload apple response',
}
export class Analytics {
static logEvent(name: Event, properties: Record<string, any>): void {
logEvent(name, properties);
@@ -1,10 +1,12 @@
import RudderAnalytics from '@expo/rudder-sdk-node';
import RudderAnalyticsModule from '@expo/rudder-sdk-node';
import os from 'os';
import { URL } from 'url';
import { v4 as uuidv4 } from 'uuid';
import UserSettings from '../user/UserSettings';
import { easCliVersion } from '../utils/easCli';
import UserSettings from '../user/UserSettings.js';
import { easCliVersion } from '../utils/easCli.js';
const RudderAnalytics = RudderAnalyticsModule.default;
const PLATFORM_TO_ANALYTICS_PLATFORM: { [platform: string]: string } = {
darwin: 'Mac',
@@ -12,7 +14,7 @@ const PLATFORM_TO_ANALYTICS_PLATFORM: { [platform: string]: string } = {
linux: 'Linux',
};
let rudderstackClient: RudderAnalytics | null = null;
let rudderstackClient: RudderAnalyticsModule.default | null = null;
let userIdentified = false;
let identifyData: {
userId: string;
+2 -2
View File
@@ -1,7 +1,7 @@
import { JSONValue } from '@expo/json-file';
import fetch, { RequestError, RequestInit } from './fetch';
import { getAccessToken, getSessionSecret } from './user/sessionStorage';
import fetch, { RequestError, RequestInit } from './fetch.js';
import { getAccessToken, getSessionSecret } from './user/sessionStorage.js';
export class ApiV2Error extends Error {
readonly name = 'ApiV2Error';
@@ -7,13 +7,16 @@ import { vol } from 'memfs';
import os from 'os';
import path from 'path';
import { getAppBuildGradleAsync, resolveConfigValue } from '../../../project/android/gradleUtils';
import {
getAppBuildGradleAsync,
resolveConfigValue,
} from '../../../project/android/gradleUtils.js';
import {
BumpStrategy,
bumpVersionAsync,
bumpVersionInAppJsonAsync,
maybeResolveVersionsAsync,
} from '../version';
} from '../version.js';
const fsReal = jest.requireActual('fs').promises as typeof fs;
jest.mock('fs');
+20 -17
View File
@@ -1,32 +1,33 @@
import { Android, Job, Metadata, Platform, Workflow } from '@expo/eas-build-job';
import chalk from 'chalk';
import nullthrows from 'nullthrows';
import AndroidCredentialsProvider, {
AndroidCredentials,
} from '../../credentials/android/AndroidCredentialsProvider';
import { BuildMutation, BuildResult } from '../../graphql/mutations/BuildMutation';
import Log from '../../log';
} from '../../credentials/android/AndroidCredentialsProvider.js';
import { BuildParamsInput } from '../../graphql/generated.js';
import { BuildMutation, BuildResult } from '../../graphql/mutations/BuildMutation.js';
import Log from '../../log.js';
import {
ensureApplicationIdIsDefinedForManagedProjectAsync,
getApplicationIdAsync,
} from '../../project/android/applicationId';
import { resolveGradleBuildContextAsync } from '../../project/android/gradle';
import { toggleConfirmAsync } from '../../prompts';
import { findAccountByName } from '../../user/Account';
} from '../../project/android/applicationId.js';
import { resolveGradleBuildContextAsync } from '../../project/android/gradle.js';
import { toggleConfirmAsync } from '../../prompts.js';
import { findAccountByName } from '../../user/Account.js';
import { nullthrows } from '../../utils/nullthrows.js';
import {
BuildRequestSender,
CredentialsResult,
JobData,
prepareBuildRequestForPlatformAsync,
} from '../build';
import { AndroidBuildContext, BuildContext, CommonContext } from '../context';
import { transformMetadata } from '../graphql';
import { logCredentialsSource } from '../utils/credentials';
import { checkGoogleServicesFileAsync, checkNodeEnvVariable } from '../validate';
import { transformJob } from './graphql';
import { prepareJobAsync } from './prepareJob';
import { syncProjectConfigurationAsync } from './syncProjectConfiguration';
} from '../build.js';
import { AndroidBuildContext, BuildContext, CommonContext } from '../context.js';
import { transformMetadata } from '../graphql.js';
import { logCredentialsSource } from '../utils/credentials.js';
import { checkGoogleServicesFileAsync, checkNodeEnvVariable } from '../validate.js';
import { transformJob } from './graphql.js';
import { prepareJobAsync } from './prepareJob.js';
import { syncProjectConfigurationAsync } from './syncProjectConfiguration.js';
export async function createAndroidContextAsync(
ctx: CommonContext<Platform.ANDROID>
@@ -87,7 +88,8 @@ export async function prepareAndroidBuildAsync(
sendBuildRequestAsync: async (
appId: string,
job: Android.Job,
metadata: Metadata
metadata: Metadata,
buildParams: BuildParamsInput
): Promise<BuildResult> => {
const graphqlMetadata = transformMetadata(metadata);
const graphqlJob = transformJob(job);
@@ -95,6 +97,7 @@ export async function prepareAndroidBuildAsync(
appId,
job: graphqlJob,
metadata: graphqlMetadata,
buildParams,
});
},
});
@@ -1,7 +1,7 @@
import { Android } from '@expo/eas-build-job';
import { AndroidBuildType, AndroidJobInput } from '../../graphql/generated';
import { transformProjectArchive, transformWorkflow } from '../graphql';
import { AndroidBuildType, AndroidJobInput } from '../../graphql/generated.js';
import { transformProjectArchive, transformWorkflow } from '../graphql.js';
export function transformJob(job: Android.Job): AndroidJobInput {
return {
@@ -3,11 +3,11 @@ import { BuildProfile } from '@expo/eas-json';
import path from 'path';
import slash from 'slash';
import { AndroidCredentials } from '../../credentials/android/AndroidCredentialsProvider';
import { getUsername } from '../../project/projectUtils';
import { ensureLoggedInAsync } from '../../user/actions';
import { getVcsClient } from '../../vcs';
import { BuildContext } from '../context';
import { AndroidCredentials } from '../../credentials/android/AndroidCredentialsProvider.js';
import { getUsername } from '../../project/projectUtils.js';
import { ensureLoggedInAsync } from '../../user/actions.js';
import { getVcsClient } from '../../vcs/index.js';
import { BuildContext } from '../context.js';
interface JobData {
projectArchive: ArchiveSource;
@@ -1,16 +1,18 @@
import { ExpoConfig } from '@expo/config';
import { AndroidConfig } from '@expo/config-plugins';
import ConfigPlugins from '@expo/config-plugins';
import { Platform, Workflow } from '@expo/eas-build-job';
import { AndroidVersionAutoIncrement, BuildProfile } from '@expo/eas-json';
import chalk from 'chalk';
import fs from 'fs-extra';
import path from 'path';
import Log from '../../log';
import { isExpoUpdatesInstalled } from '../../project/projectUtils';
import { resolveWorkflowAsync } from '../../project/workflow';
import { syncUpdatesConfigurationAsync } from '../../update/android/UpdatesModule';
import { BumpStrategy, bumpVersionAsync, bumpVersionInAppJsonAsync } from './version';
import Log from '../../log.js';
import { isExpoUpdatesInstalled } from '../../project/projectUtils.js';
import { resolveWorkflowAsync } from '../../project/workflow.js';
import { syncUpdatesConfigurationAsync } from '../../update/android/UpdatesModule.js';
import { BumpStrategy, bumpVersionAsync, bumpVersionInAppJsonAsync } from './version.js';
const { AndroidConfig } = ConfigPlugins;
export async function syncProjectConfigurationAsync({
projectDir,
@@ -1,19 +1,21 @@
import { ExpoConfig } from '@expo/config';
import { AndroidConfig } from '@expo/config-plugins';
import ConfigPlugins from '@expo/config-plugins';
import { Platform, Workflow } from '@expo/eas-build-job';
import { BuildProfile } from '@expo/eas-json';
import chalk from 'chalk';
import fs from 'fs-extra';
import Log from '../../log';
import Log from '../../log.js';
import {
getAppBuildGradleAsync,
parseGradleCommand,
resolveConfigValue,
} from '../../project/android/gradleUtils';
import { resolveWorkflowAsync } from '../../project/workflow';
import { updateAppJsonConfigAsync } from '../utils/appJson';
import { bumpAppVersionAsync, ensureStaticConfigExists } from '../utils/version';
} from '../../project/android/gradleUtils.js';
import { resolveWorkflowAsync } from '../../project/workflow.js';
import { updateAppJsonConfigAsync } from '../utils/appJson.js';
import { bumpAppVersionAsync, ensureStaticConfigExists } from '../utils/version.js';
const { AndroidConfig } = ConfigPlugins;
export enum BumpStrategy {
APP_VERSION,
@@ -105,7 +107,7 @@ export async function maybeResolveVersionsAsync(
appBuildVersion:
resolveConfigValue(buildGradle, 'versionCode', parsedGradleCommand?.flavor) ?? '1',
};
} catch (err: any) {
} catch {
return {};
}
} else {
+66 -40
View File
@@ -3,37 +3,38 @@ import { CredentialsSource } from '@expo/eas-json';
import chalk from 'chalk';
import cliProgress from 'cli-progress';
import fs from 'fs-extra';
import nullthrows from 'nullthrows';
import { withAnalyticsAsync } from '../analytics/common';
import { BuildEvent } from '../analytics/events';
import { getExpoWebsiteBaseUrl } from '../api';
import { withAnalyticsAsync } from '../analytics/common.js';
import { BuildEvent } from '../analytics/events.js';
import { getExpoWebsiteBaseUrl } from '../api.js';
import {
AppPlatform,
BuildFragment,
BuildParamsInput,
BuildPriority,
BuildStatus,
UploadSessionType,
} from '../graphql/generated';
import { BuildResult } from '../graphql/mutations/BuildMutation';
import { BuildQuery } from '../graphql/queries/BuildQuery';
import Log, { learnMore } from '../log';
import { Ora, ora } from '../ora';
} from '../graphql/generated.js';
import { BuildResult } from '../graphql/mutations/BuildMutation.js';
import { BuildQuery } from '../graphql/queries/BuildQuery.js';
import Log, { learnMore } from '../log.js';
import { Ora, ora } from '../ora.js';
import {
appPlatformDisplayNames,
appPlatformEmojis,
requestedPlatformDisplayNames,
} from '../platform';
import { uploadAsync } from '../uploads';
import { formatBytes } from '../utils/files';
import { createProgressTracker } from '../utils/progress';
import { sleepAsync } from '../utils/promise';
import { getVcsClient } from '../vcs';
import { BuildContext } from './context';
import { runLocalBuildAsync } from './local';
import { collectMetadataAsync } from './metadata';
import { printDeprecationWarnings } from './utils/printBuildInfo';
import { makeProjectTarballAsync, reviewAndCommitChangesAsync } from './utils/repository';
} from '../platform.js';
import { uploadAsync } from '../uploads.js';
import { formatBytes } from '../utils/files.js';
import { nullthrows } from '../utils/nullthrows.js';
import { createProgressTracker } from '../utils/progress.js';
import { sleepAsync } from '../utils/promise.js';
import { getVcsClient } from '../vcs/index.js';
import { BuildContext } from './context.js';
import { runLocalBuildAsync } from './local.js';
import { collectMetadataAsync } from './metadata.js';
import { printDeprecationWarnings } from './utils/printBuildInfo.js';
import { makeProjectTarballAsync, reviewAndCommitChangesAsync } from './utils/repository.js';
export interface CredentialsResult<Credentials> {
source: CredentialsSource.LOCAL | CredentialsSource.REMOTE;
@@ -53,11 +54,22 @@ interface Builder<TPlatform extends Platform, Credentials, TJob extends Job> {
): Promise<CredentialsResult<Credentials> | undefined>;
syncProjectConfigurationAsync(ctx: BuildContext<TPlatform>): Promise<void>;
prepareJobAsync(ctx: BuildContext<TPlatform>, jobData: JobData<Credentials>): Promise<Job>;
sendBuildRequestAsync(appId: string, job: TJob, metadata: Metadata): Promise<BuildResult>;
sendBuildRequestAsync(
appId: string,
job: TJob,
metadata: Metadata,
buildParams: BuildParamsInput
): Promise<BuildResult>;
}
export type BuildRequestSender = () => Promise<BuildFragment | undefined>;
function resolveBuildParamsInput<T extends Platform>(ctx: BuildContext<T>): BuildParamsInput {
return {
resourceClass: ctx.resourceClass,
};
}
export async function prepareBuildRequestForPlatformAsync<
TPlatform extends Platform,
Credentials,
@@ -100,6 +112,7 @@ export async function prepareBuildRequestForPlatformAsync<
} as const);
const metadata = await collectMetadataAsync(ctx);
const buildParams = resolveBuildParamsInput(ctx);
const job = await builder.prepareJobAsync(ctx, {
projectArchive,
credentials: credentialsResult?.credentials,
@@ -111,7 +124,7 @@ export async function prepareBuildRequestForPlatformAsync<
return undefined;
} else {
try {
return await sendBuildRequestAsync(builder, job, metadata);
return await sendBuildRequestAsync(builder, job, metadata, buildParams);
} catch (error: any) {
handleBuildRequestError(error, job.platform);
}
@@ -157,6 +170,12 @@ async function uploadProjectAsync<TPlatform extends Platform>(
try {
return await withAnalyticsAsync(
async () => {
Log.newLine();
Log.log(
`Compressing project files and uploading to EAS Build. ${learnMore(
'https://expo.fyi/eas-build-archive'
)}`
);
const projectTarball = await makeProjectTarballAsync();
projectTarballPath = projectTarball.path;
@@ -169,10 +188,7 @@ async function uploadProjectAsync<TPlatform extends Platform>(
`Uploading to EAS Build (${formatBytes(projectTarball.size * ratio)} / ${formatBytes(
projectTarball.size
)})`,
completedMessage: (duration: string) =>
`Uploaded to EAS ${chalk.dim(duration)} ${learnMore(
'https://expo.fyi/eas-build-archive'
)}`,
completedMessage: (duration: string) => `Uploaded to EAS ${chalk.dim(duration)}`,
})
);
return bucketKey;
@@ -194,7 +210,8 @@ async function uploadProjectAsync<TPlatform extends Platform>(
async function sendBuildRequestAsync<TPlatform extends Platform, Credentials, TJob extends Job>(
builder: Builder<TPlatform, Credentials, TJob>,
job: TJob,
metadata: Metadata
metadata: Metadata,
buildParams: BuildParamsInput
): Promise<BuildFragment> {
const { ctx } = builder;
return await withAnalyticsAsync(
@@ -206,7 +223,8 @@ async function sendBuildRequestAsync<TPlatform extends Platform, Credentials, TJ
const { build, deprecationInfo } = await builder.sendBuildRequestAsync(
ctx.projectId,
job,
metadata
metadata,
buildParams
);
printDeprecationWarnings(deprecationInfo);
@@ -226,21 +244,28 @@ type MaybeBuildFragment = BuildFragment | null;
export async function waitForBuildEndAsync(
{ buildIds, accountName }: { buildIds: string[]; accountName: string },
{
// 2 hours (max build time limit) + 10 minutes (possible queue time )
// 2 hours (max build time limit) + 10 minutes (possible queue time)
timeoutSec = 2 * 60 * 60 + 10 * 60,
intervalSec = 10,
} = {}
): Promise<MaybeBuildFragment[]> {
const b = `build${buildIds.length > 1 ? 's' : ''}`;
Log.log(`Waiting for ${b} to complete. You can press Ctrl+C to exit.`);
const spinner = ora(`Waiting for ${b} to complete.`).start();
let spinner;
let originalSpinnerText;
if (buildIds.length === 1) {
Log.log('Waiting for build to complete. You can press Ctrl+C to exit.');
originalSpinnerText = 'Waiting for build to complete.';
spinner = ora(originalSpinnerText).start();
} else {
originalSpinnerText = 'Waiting for builds to complete. You can press Ctrl+C to exit.';
spinner = ora('Waiting for builds to complete. You can press Ctrl+C to exit.').start();
}
const endTime = new Date().getTime() + timeoutSec * 1000;
while (new Date().getTime() <= endTime) {
const builds = await getBuildsSafelyAsync(buildIds);
const { refetch } =
builds.length === 1
? await handleSingleBuildProgressAsync({ build: builds[0], accountName }, { spinner })
: await handleMultipleBuildsProgressAsync({ builds }, { spinner });
: await handleMultipleBuildsProgressAsync({ builds }, { spinner, originalSpinnerText });
if (!refetch) {
return builds;
}
@@ -373,7 +398,7 @@ const platforms = [AppPlatform.Android, AppPlatform.Ios];
async function handleMultipleBuildsProgressAsync(
{ builds: maybeBuilds }: { builds: MaybeBuildFragment[] },
{ spinner }: { spinner: Ora }
{ spinner, originalSpinnerText }: { spinner: Ora; originalSpinnerText: string }
): Promise<BuildProgressResult> {
const buildCount = maybeBuilds.length;
const builds = maybeBuilds.filter<BuildFragment>(isBuildFragment);
@@ -393,7 +418,7 @@ async function handleMultipleBuildsProgressAsync(
}
return { refetch: false };
} else {
spinner.text = formatPendingBuildsText(builds);
spinner.text = formatPendingBuildsText(originalSpinnerText, builds);
return { refetch: true };
}
}
@@ -412,9 +437,10 @@ function formatSettledBuildsText(builds: BuildFragment[]): string {
.join('\n ');
}
function formatPendingBuildsText(builds: BuildFragment[]): string {
return platforms
.map(platform => {
function formatPendingBuildsText(originalSpinnerText: string, builds: BuildFragment[]): string {
return [
originalSpinnerText,
...platforms.map(platform => {
const build = builds.find(build => build.platform === platform);
const status = build ? statusToDisplayName[build.status] : 'unknown';
let extraInfo = '';
@@ -437,8 +463,8 @@ function formatPendingBuildsText(builds: BuildFragment[]): string {
return `${appPlatformEmojis[platform]} ${
appPlatformDisplayNames[platform]
} build - status: ${chalk.bold(status)}${extraInfo}`;
})
.join('\n ');
}),
].join('\n ');
}
function isBuildFragment(maybeBuild: MaybeBuildFragment): maybeBuild is BuildFragment {
+5 -5
View File
@@ -3,11 +3,11 @@ import { EasJson, EasJsonReader } from '@expo/eas-json';
import chalk from 'chalk';
import fs from 'fs-extra';
import Log from '../log';
import { resolveWorkflowAsync } from '../project/workflow';
import { easCliVersion } from '../utils/easCli';
import { getVcsClient } from '../vcs';
import { maybeBailOnRepoStatusAsync, reviewAndCommitChangesAsync } from './utils/repository';
import Log from '../log.js';
import { resolveWorkflowAsync } from '../project/workflow.js';
import { easCliVersion } from '../utils/easCli.js';
import { getVcsClient } from '../vcs/index.js';
import { maybeBailOnRepoStatusAsync, reviewAndCommitChangesAsync } from './utils/repository.js';
interface ConfigureParams {
projectDir: string;
+9 -7
View File
@@ -3,13 +3,14 @@ import { Platform, Workflow } from '@expo/eas-build-job';
import { BuildProfile } from '@expo/eas-json';
import type { XCBuildConfiguration } from 'xcode';
import { TrackingContext } from '../analytics/common';
import { CredentialsContext } from '../credentials/context';
import { Target } from '../credentials/ios/types';
import { GradleBuildContext } from '../project/android/gradle';
import { XcodeBuildContext } from '../project/ios/scheme';
import { Actor } from '../user/User';
import { LocalBuildOptions } from './local';
import { TrackingContext } from '../analytics/common.js';
import { CredentialsContext } from '../credentials/context.js';
import { Target } from '../credentials/ios/types.js';
import { BuildResourceClass } from '../graphql/generated.js';
import { GradleBuildContext } from '../project/android/gradle.js';
import { XcodeBuildContext } from '../project/ios/scheme.js';
import { Actor } from '../user/User.js';
import { LocalBuildOptions } from './local.js';
export type CommonContext<T extends Platform> = Omit<BuildContext<T>, 'android' | 'ios'>;
@@ -30,6 +31,7 @@ export interface BuildContext<T extends Platform> {
accountName: string;
buildProfile: BuildProfile<T>;
buildProfileName: string;
resourceClass: BuildResourceClass;
clearCache: boolean;
credentialsCtx: CredentialsContext;
exp: ExpoConfig;
+19 -13
View File
@@ -1,21 +1,24 @@
import { Platform } from '@expo/eas-build-job';
import { BuildProfile } from '@expo/eas-json';
import JsonFile from '@expo/json-file';
import JsonFileModule from '@expo/json-file';
import resolveFrom from 'resolve-from';
import { v4 as uuidv4 } from 'uuid';
import { TrackingContext } from '../analytics/common';
import { Analytics, BuildEvent } from '../analytics/events';
import { CredentialsContext } from '../credentials/context';
import { getExpoConfig } from '../project/expoConfig';
import { getProjectAccountName, getProjectIdAsync } from '../project/projectUtils';
import { resolveWorkflowAsync } from '../project/workflow';
import { findAccountByName } from '../user/Account';
import { ensureLoggedInAsync } from '../user/actions';
import { createAndroidContextAsync } from './android/build';
import { BuildContext, CommonContext } from './context';
import { createIosContextAsync } from './ios/build';
import { LocalBuildOptions } from './local';
import { TrackingContext } from '../analytics/common.js';
import { Analytics, BuildEvent } from '../analytics/events.js';
import { CredentialsContext } from '../credentials/context.js';
import { BuildResourceClass } from '../graphql/generated.js';
import { getExpoConfig } from '../project/expoConfig.js';
import { getProjectAccountName, getProjectIdAsync } from '../project/projectUtils.js';
import { resolveWorkflowAsync } from '../project/workflow.js';
import { findAccountByName } from '../user/Account.js';
import { ensureLoggedInAsync } from '../user/actions.js';
import { createAndroidContextAsync } from './android/build.js';
import { BuildContext, CommonContext } from './context.js';
import { createIosContextAsync } from './ios/build.js';
import { LocalBuildOptions } from './local.js';
const JsonFile = JsonFileModule.default;
export async function createBuildContextAsync<T extends Platform>({
buildProfileName,
@@ -25,6 +28,7 @@ export async function createBuildContextAsync<T extends Platform>({
nonInteractive = false,
platform,
projectDir,
resourceClass,
}: {
buildProfileName: string;
buildProfile: BuildProfile<T>;
@@ -33,6 +37,7 @@ export async function createBuildContextAsync<T extends Platform>({
nonInteractive: boolean;
platform: T;
projectDir: string;
resourceClass: BuildResourceClass;
}): Promise<BuildContext<T>> {
const exp = getExpoConfig(projectDir, { env: buildProfile.env });
@@ -70,6 +75,7 @@ export async function createBuildContextAsync<T extends Platform>({
accountName,
buildProfile,
buildProfileName,
resourceClass,
clearCache,
credentialsCtx,
exp,
+1 -1
View File
@@ -8,7 +8,7 @@ import {
DistributionType,
ProjectArchiveSourceInput,
ProjectArchiveSourceType,
} from '../graphql/generated';
} from '../graphql/generated.js';
export function transformProjectArchive(archiveSource: ArchiveSource): ProjectArchiveSourceInput {
if (archiveSource.type === ArchiveSourceType.S3) {
@@ -1,10 +1,10 @@
import { ExpoConfig } from '@expo/config';
import { IOSConfig } from '@expo/config-plugins';
import { InfoPlist } from '@expo/config-plugins';
import fs from 'fs-extra';
import { vol } from 'memfs';
import os from 'os';
import { readPlistAsync } from '../../../utils/plist';
import { readPlistAsync } from '../../../utils/plist.js';
import {
BumpStrategy,
bumpVersionAsync,
@@ -13,7 +13,7 @@ import {
getInfoPlistPath,
readBuildNumberAsync,
readShortVersionAsync,
} from '../version';
} from '../version.js';
jest.mock('fs');
@@ -62,9 +62,7 @@ describe(bumpVersionAsync, () => {
});
const appJSON = await fs.readJSON('/repo/app.json');
const infoPlist = (await readPlistAsync(
'/repo/ios/myproject/Info.plist'
)) as IOSConfig.InfoPlist;
const infoPlist = (await readPlistAsync('/repo/ios/myproject/Info.plist')) as InfoPlist;
expect(fakeExp.version).toBe('1.0.0');
expect(fakeExp.ios?.buildNumber).toBe('2');
expect(appJSON.expo.version).toBe('1.0.0');
@@ -86,9 +84,7 @@ describe(bumpVersionAsync, () => {
});
const appJSON = await fs.readJSON('/repo/app.json');
const infoPlist = (await readPlistAsync(
'/repo/ios/myproject/Info2.plist'
)) as IOSConfig.InfoPlist;
const infoPlist = (await readPlistAsync('/repo/ios/myproject/Info2.plist')) as InfoPlist;
expect(fakeExp.version).toBe('1.0.0');
expect(fakeExp.ios?.buildNumber).toBe('2');
expect(appJSON.expo.version).toBe('1.0.0');
@@ -108,9 +104,7 @@ describe(bumpVersionAsync, () => {
});
const appJSON = await fs.readJSON('/repo/app.json');
const infoPlist = (await readPlistAsync(
'/repo/ios/myproject/Info.plist'
)) as IOSConfig.InfoPlist;
const infoPlist = (await readPlistAsync('/repo/ios/myproject/Info.plist')) as InfoPlist;
expect(fakeExp.version).toBe('1.0.1');
expect(fakeExp.ios?.buildNumber).toBe('1');
expect(appJSON.expo.version).toBe('1.0.1');
@@ -130,9 +124,7 @@ describe(bumpVersionAsync, () => {
});
const appJSON = await fs.readJSON('/repo/app.json');
const infoPlist = (await readPlistAsync(
'/repo/ios/myproject/Info.plist'
)) as IOSConfig.InfoPlist;
const infoPlist = (await readPlistAsync('/repo/ios/myproject/Info.plist')) as InfoPlist;
expect(fakeExp.version).toBe('1.0.0');
expect(fakeExp.ios?.buildNumber).toBe('1');
expect(appJSON.expo.version).toBe('1.0.0');
+26 -22
View File
@@ -1,20 +1,23 @@
import { IOSConfig } from '@expo/config-plugins';
import ConfigPlugins from '@expo/config-plugins';
import { Ios, Job, Metadata, Platform, Workflow } from '@expo/eas-build-job';
import type { XCBuildConfiguration } from 'xcode';
import { IosCredentials, Target } from '../../credentials/ios/types';
import { BuildMutation, BuildResult } from '../../graphql/mutations/BuildMutation';
import { ensureBundleIdentifierIsDefinedForManagedProjectAsync } from '../../project/ios/bundleIdentifier';
import { resolveXcodeBuildContextAsync } from '../../project/ios/scheme';
import { findApplicationTarget, resolveTargetsAsync } from '../../project/ios/target';
import { BuildRequestSender, JobData, prepareBuildRequestForPlatformAsync } from '../build';
import { BuildContext, CommonContext, IosBuildContext } from '../context';
import { transformMetadata } from '../graphql';
import { checkGoogleServicesFileAsync, checkNodeEnvVariable } from '../validate';
import { ensureIosCredentialsAsync } from './credentials';
import { transformJob } from './graphql';
import { prepareJobAsync } from './prepareJob';
import { syncProjectConfigurationAsync } from './syncProjectConfiguration';
import { IosCredentials, Target } from '../../credentials/ios/types.js';
import { BuildParamsInput } from '../../graphql/generated.js';
import { BuildMutation, BuildResult } from '../../graphql/mutations/BuildMutation.js';
import { ensureBundleIdentifierIsDefinedForManagedProjectAsync } from '../../project/ios/bundleIdentifier.js';
import { resolveXcodeBuildContextAsync } from '../../project/ios/scheme.js';
import { findApplicationTarget, resolveTargetsAsync } from '../../project/ios/target.js';
import { BuildRequestSender, JobData, prepareBuildRequestForPlatformAsync } from '../build.js';
import { BuildContext, CommonContext, IosBuildContext } from '../context.js';
import { transformMetadata } from '../graphql.js';
import { checkGoogleServicesFileAsync, checkNodeEnvVariable } from '../validate.js';
import { ensureIosCredentialsAsync } from './credentials.js';
import { transformJob } from './graphql.js';
import { prepareJobAsync } from './prepareJob.js';
import { syncProjectConfigurationAsync } from './syncProjectConfiguration.js';
const { IOSConfig } = ConfigPlugins;
export async function createIosContextAsync(
ctx: CommonContext<Platform.IOS>
@@ -36,13 +39,12 @@ export async function createIosContextAsync(
},
buildProfile
);
const targets = await resolveTargetsAsync(
{
projectDir: ctx.projectDir,
exp: ctx.exp,
},
xcodeBuildContext
);
const targets = await resolveTargetsAsync({
projectDir: ctx.projectDir,
exp: ctx.exp,
xcodeBuildContext,
env: buildProfile.env,
});
const applicationTarget = findApplicationTarget(targets);
const applicationTargetBuildSettings = resolveBuildSettings(ctx, applicationTarget);
@@ -83,7 +85,8 @@ export async function prepareIosBuildAsync(
sendBuildRequestAsync: async (
appId: string,
job: Ios.Job,
metadata: Metadata
metadata: Metadata,
buildParams: BuildParamsInput
): Promise<BuildResult> => {
const graphqlMetadata = transformMetadata(metadata);
const graphqlJob = transformJob(job);
@@ -91,6 +94,7 @@ export async function prepareIosBuildAsync(
appId,
job: graphqlJob,
metadata: graphqlMetadata,
buildParams,
});
},
});
+6 -14
View File
@@ -1,12 +1,11 @@
import { Platform } from '@expo/eas-build-job';
import IosCredentialsProvider from '../../credentials/ios/IosCredentialsProvider';
import { getAppFromContext } from '../../credentials/ios/actions/BuildCredentialsUtils';
import { resolveEntitlementsJsonAsync } from '../../credentials/ios/appstore/entitlements';
import { IosCredentials, Target } from '../../credentials/ios/types';
import { CredentialsResult } from '../build';
import { BuildContext } from '../context';
import { logCredentialsSource } from '../utils/credentials';
import IosCredentialsProvider from '../../credentials/ios/IosCredentialsProvider.js';
import { getAppFromContext } from '../../credentials/ios/actions/BuildCredentialsUtils.js';
import { IosCredentials, Target } from '../../credentials/ios/types.js';
import { CredentialsResult } from '../build.js';
import { BuildContext } from '../context.js';
import { logCredentialsSource } from '../utils/credentials.js';
export async function ensureIosCredentialsAsync(
buildCtx: BuildContext<Platform.IOS>,
@@ -19,13 +18,6 @@ export async function ensureIosCredentialsAsync(
const provider = new IosCredentialsProvider(buildCtx.credentialsCtx, {
app: getAppFromContext(buildCtx.credentialsCtx),
targets,
iosCapabilitiesOptions: {
entitlements: await resolveEntitlementsJsonAsync(
buildCtx.projectDir,
buildCtx.workflow,
buildCtx.buildProfile.env ?? {}
),
},
distribution: buildCtx.buildProfile.distribution ?? 'store',
enterpriseProvisioning: buildCtx.buildProfile.enterpriseProvisioning,
});
+3 -3
View File
@@ -1,8 +1,8 @@
import { Env, Ios } from '@expo/eas-build-job';
import nullthrows from 'nullthrows';
import { IosJobInput, IosJobSecretsInput } from '../../graphql/generated';
import { transformProjectArchive, transformWorkflow } from '../graphql';
import { IosJobInput, IosJobSecretsInput } from '../../graphql/generated.js';
import { nullthrows } from '../../utils/nullthrows.js';
import { transformProjectArchive, transformWorkflow } from '../graphql.js';
export function transformJob(job: Ios.Job): IosJobInput {
return {
+5 -5
View File
@@ -2,11 +2,11 @@ import { ArchiveSource, Ios, Job, Platform, sanitizeJob } from '@expo/eas-build-
import path from 'path';
import slash from 'slash';
import { IosCredentials, TargetCredentials } from '../../credentials/ios/types';
import { getUsername } from '../../project/projectUtils';
import { ensureLoggedInAsync } from '../../user/actions';
import { getVcsClient } from '../../vcs';
import { BuildContext } from '../context';
import { IosCredentials, TargetCredentials } from '../../credentials/ios/types.js';
import { getUsername } from '../../project/projectUtils.js';
import { ensureLoggedInAsync } from '../../user/actions.js';
import { getVcsClient } from '../../vcs/index.js';
import { BuildContext } from '../context.js';
interface JobData {
projectArchive: ArchiveSource;
@@ -3,10 +3,10 @@ import { Platform, Workflow } from '@expo/eas-build-job';
import { BuildProfile, IosVersionAutoIncrement } from '@expo/eas-json';
import type { XCBuildConfiguration } from 'xcode';
import { isExpoUpdatesInstalled } from '../../project/projectUtils';
import { resolveWorkflowAsync } from '../../project/workflow';
import { syncUpdatesConfigurationAsync } from '../../update/ios/UpdatesModule';
import { BumpStrategy, bumpVersionAsync, bumpVersionInAppJsonAsync } from './version';
import { isExpoUpdatesInstalled } from '../../project/projectUtils.js';
import { resolveWorkflowAsync } from '../../project/workflow.js';
import { syncUpdatesConfigurationAsync } from '../../update/ios/UpdatesModule.js';
import { BumpStrategy, bumpVersionAsync, bumpVersionInAppJsonAsync } from './version.js';
export async function syncProjectConfigurationAsync({
projectDir,
+14 -12
View File
@@ -1,16 +1,18 @@
import { ExpoConfig, getConfigFilePaths } from '@expo/config';
import { IOSConfig } from '@expo/config-plugins';
import ConfigPlugins, { InfoPlist } from '@expo/config-plugins';
import { Platform, Workflow } from '@expo/eas-build-job';
import chalk from 'chalk';
import path from 'path';
import type { XCBuildConfiguration } from 'xcode';
import Log from '../../log';
import { resolveWorkflowAsync } from '../../project/workflow';
import { promptAsync } from '../../prompts';
import { readPlistAsync, writePlistAsync } from '../../utils/plist';
import { updateAppJsonConfigAsync } from '../utils/appJson';
import { bumpAppVersionAsync } from '../utils/version';
import Log from '../../log.js';
import { resolveWorkflowAsync } from '../../project/workflow.js';
import { promptAsync } from '../../prompts.js';
import { readPlistAsync, writePlistAsync } from '../../utils/plist.js';
import { updateAppJsonConfigAsync } from '../utils/appJson.js';
import { bumpAppVersionAsync } from '../utils/version.js';
const { IOSConfig } = ConfigPlugins;
export enum BumpStrategy {
APP_VERSION,
@@ -145,9 +147,9 @@ async function writeVersionsToInfoPlistAsync({
}: {
projectDir: string;
exp: ExpoConfig;
infoPlist: IOSConfig.InfoPlist;
infoPlist: InfoPlist;
buildSettings: XCBuildConfiguration['buildSettings'];
}): Promise<IOSConfig.InfoPlist> {
}): Promise<InfoPlist> {
let updatedInfoPlist = IOSConfig.Version.setVersion(exp, infoPlist);
updatedInfoPlist = IOSConfig.Version.setBuildNumber(exp, updatedInfoPlist);
await writeInfoPlistAsync({ projectDir, infoPlist: updatedInfoPlist, buildSettings });
@@ -176,9 +178,9 @@ export function getInfoPlistPath(
async function readInfoPlistAsync(
projectDir: string,
buildSettings: XCBuildConfiguration['buildSettings']
): Promise<IOSConfig.InfoPlist> {
): Promise<InfoPlist> {
const infoPlistPath = getInfoPlistPath(projectDir, buildSettings);
return ((await readPlistAsync(infoPlistPath)) ?? {}) as IOSConfig.InfoPlist;
return ((await readPlistAsync(infoPlistPath)) ?? {}) as InfoPlist;
}
async function writeInfoPlistAsync({
@@ -187,7 +189,7 @@ async function writeInfoPlistAsync({
buildSettings,
}: {
projectDir: string;
infoPlist: IOSConfig.InfoPlist;
infoPlist: InfoPlist;
buildSettings: XCBuildConfiguration['buildSettings'];
}): Promise<void> {
const infoPlistPath = getInfoPlistPath(projectDir, buildSettings);
+3 -3
View File
@@ -1,12 +1,12 @@
import { Job } from '@expo/eas-build-job';
import spawnAsync from '@expo/spawn-async';
import { default as spawnAsync } from '@expo/spawn-async';
import { ChildProcess } from 'child_process';
import semver from 'semver';
import { ora } from '../ora';
import { ora } from '../ora.js';
const PLUGIN_PACKAGE_NAME = 'eas-cli-local-build-plugin';
const PLUGIN_PACKAGE_VERSION = '0.0.74';
const PLUGIN_PACKAGE_VERSION = '0.0.85';
export interface LocalBuildOptions {
enable: boolean;
+13 -11
View File
@@ -1,25 +1,27 @@
import { Updates } from '@expo/config-plugins';
import ConfigPlugins from '@expo/config-plugins';
import { Metadata, Platform, sanitizeMetadata } from '@expo/eas-build-job';
import { IosEnterpriseProvisioning } from '@expo/eas-json';
import fs from 'fs-extra';
import resolveFrom from 'resolve-from';
import Log from '../log';
import { getUsername, isExpoUpdatesInstalled } from '../project/projectUtils';
import Log from '../log.js';
import { getUsername, isExpoUpdatesInstalled } from '../project/projectUtils.js';
import {
readChannelSafelyAsync as readAndroidChannelSafelyAsync,
readReleaseChannelSafelyAsync as readAndroidReleaseChannelSafelyAsync,
} from '../update/android/UpdatesModule';
} from '../update/android/UpdatesModule.js';
import {
readChannelSafelyAsync as readIosChannelSafelyAsync,
readReleaseChannelSafelyAsync as readIosReleaseChannelSafelyAsync,
} from '../update/ios/UpdatesModule';
import { ensureLoggedInAsync } from '../user/actions';
import { easCliVersion } from '../utils/easCli';
import { getVcsClient } from '../vcs';
import { maybeResolveVersionsAsync as maybeResolveAndroidVersionsAsync } from './android/version';
import { BuildContext } from './context';
import { maybeResolveVersionsAsync as maybeResolveIosVersionsAsync } from './ios/version';
} from '../update/ios/UpdatesModule.js';
import { ensureLoggedInAsync } from '../user/actions.js';
import { easCliVersion } from '../utils/easCli.js';
import { getVcsClient } from '../vcs/index.js';
import { maybeResolveVersionsAsync as maybeResolveAndroidVersionsAsync } from './android/version.js';
import { BuildContext } from './context.js';
import { maybeResolveVersionsAsync as maybeResolveIosVersionsAsync } from './ios/version.js';
const { Updates } = ConfigPlugins;
export async function collectMetadataAsync<T extends Platform>(
ctx: BuildContext<T>
+56 -26
View File
@@ -1,38 +1,45 @@
import { Platform, Workflow } from '@expo/eas-build-job';
import { BuildProfile, SubmitProfile } from '@expo/eas-json';
import { BuildProfile, EasJsonReader, SubmitProfile } from '@expo/eas-json';
import chalk from 'chalk';
import nullthrows from 'nullthrows';
import { AppPlatform, BuildFragment, BuildStatus, SubmissionFragment } from '../graphql/generated';
import { toAppPlatform, toPlatform } from '../graphql/types/AppPlatform';
import Log from '../log';
import {
AppPlatform,
BuildFragment,
BuildResourceClass,
BuildStatus,
SubmissionFragment,
} from '../graphql/generated.js';
import { toAppPlatform, toPlatform } from '../graphql/types/AppPlatform.js';
import Log from '../log.js';
import {
RequestedPlatform,
appPlatformDisplayNames,
appPlatformEmojis,
toPlatforms,
} from '../platform';
import { checkExpoSdkIsSupportedAsync } from '../project/expoSdk';
import { validateMetroConfigForManagedWorkflowAsync } from '../project/metroConfig';
import { createSubmissionContextAsync } from '../submit/context';
} from '../platform.js';
import { checkExpoSdkIsSupportedAsync } from '../project/expoSdk.js';
import { validateMetroConfigForManagedWorkflowAsync } from '../project/metroConfig.js';
import { createSubmissionContextAsync } from '../submit/context.js';
import {
submitAsync,
waitToCompleteAsync as waitForSubmissionsToCompleteAsync,
} from '../submit/submit';
import { printSubmissionDetailsUrls } from '../submit/utils/urls';
import { printJsonOnlyOutput } from '../utils/json';
import { ProfileData, getProfilesAsync } from '../utils/profiles';
import { getVcsClient } from '../vcs';
import { prepareAndroidBuildAsync } from './android/build';
import { BuildRequestSender, waitForBuildEndAsync } from './build';
import { ensureProjectConfiguredAsync } from './configure';
import { BuildContext } from './context';
import { createBuildContextAsync } from './createContext';
import { prepareIosBuildAsync } from './ios/build';
import { LocalBuildOptions } from './local';
import { ensureExpoDevClientInstalledForDevClientBuildsAsync } from './utils/devClient';
import { printBuildResults, printLogsUrls } from './utils/printBuildInfo';
import { ensureRepoIsCleanAsync } from './utils/repository';
} from '../submit/submit.js';
import { printSubmissionDetailsUrls } from '../submit/utils/urls.js';
import { printJsonOnlyOutput } from '../utils/json.js';
import { nullthrows } from '../utils/nullthrows.js';
import { ProfileData, getProfilesAsync } from '../utils/profiles.js';
import { getVcsClient } from '../vcs/index.js';
import { prepareAndroidBuildAsync } from './android/build.js';
import { BuildRequestSender, waitForBuildEndAsync } from './build.js';
import { ensureProjectConfiguredAsync } from './configure.js';
import { BuildContext } from './context.js';
import { createBuildContextAsync } from './createContext.js';
import { prepareIosBuildAsync } from './ios/build.js';
import { LocalBuildOptions } from './local.js';
import { UserInputResourceClass } from './types.js';
import { ensureExpoDevClientInstalledForDevClientBuildsAsync } from './utils/devClient.js';
import { printBuildResults, printLogsUrls } from './utils/printBuildInfo.js';
import { ensureRepoIsCleanAsync } from './utils/repository.js';
let metroConfigValidated = false;
let sdkVersionChecked = false;
@@ -47,8 +54,23 @@ export interface BuildFlags {
autoSubmit: boolean;
submitProfile?: string;
localBuildOptions: LocalBuildOptions;
userInputResourceClass?: UserInputResourceClass;
}
const platformToGraphQLResourceClassMapping: Record<
Platform,
Record<UserInputResourceClass, BuildResourceClass>
> = {
[Platform.ANDROID]: {
[UserInputResourceClass.DEFAULT]: BuildResourceClass.AndroidDefault,
[UserInputResourceClass.LARGE]: BuildResourceClass.AndroidLarge,
},
[Platform.IOS]: {
[UserInputResourceClass.DEFAULT]: BuildResourceClass.IosDefault,
[UserInputResourceClass.LARGE]: BuildResourceClass.IosLarge,
},
};
export async function runBuildAndSubmitAsync(projectDir: string, flags: BuildFlags): Promise<void> {
await getVcsClient().ensureRepoExistsAsync();
await ensureRepoIsCleanAsync(flags.nonInteractive);
@@ -57,11 +79,12 @@ export async function runBuildAndSubmitAsync(projectDir: string, flags: BuildFla
projectDir,
nonInteractive: flags.nonInteractive,
});
const easJsonReader = new EasJsonReader(projectDir);
const platforms = toPlatforms(flags.requestedPlatform);
const buildProfiles = await getProfilesAsync({
type: 'build',
projectDir,
easJsonReader,
platforms,
profileName: flags.profile ?? undefined,
});
@@ -84,6 +107,10 @@ export async function runBuildAndSubmitAsync(projectDir: string, flags: BuildFla
flags,
moreBuilds: platforms.length > 1,
buildProfile,
resourceClass:
platformToGraphQLResourceClassMapping[buildProfile.platform][
flags.userInputResourceClass ?? UserInputResourceClass.DEFAULT
],
});
if (maybeBuild) {
startedBuilds.push({ build: maybeBuild, buildProfile });
@@ -102,7 +129,7 @@ export async function runBuildAndSubmitAsync(projectDir: string, flags: BuildFla
const submissions: SubmissionFragment[] = [];
if (flags.autoSubmit) {
const submitProfiles = await getProfilesAsync({
projectDir,
easJsonReader,
platforms,
profileName: flags.submitProfile,
type: 'submit',
@@ -160,14 +187,17 @@ async function prepareAndStartBuildAsync({
flags,
moreBuilds,
buildProfile,
resourceClass,
}: {
projectDir: string;
flags: BuildFlags;
moreBuilds: boolean;
buildProfile: ProfileData<'build'>;
resourceClass: BuildResourceClass;
}): Promise<{ build: BuildFragment | undefined; buildCtx: BuildContext<Platform> }> {
const buildCtx = await createBuildContextAsync({
buildProfileName: buildProfile.profileName,
resourceClass,
clearCache: flags.clearCache,
buildProfile: buildProfile.profile,
nonInteractive: flags.nonInteractive,
+5
View File
@@ -12,3 +12,8 @@ export enum BuildDistributionType {
INTERNAL = 'internal',
SIMULATOR = 'simulator',
}
export enum UserInputResourceClass {
DEFAULT = 'default',
LARGE = 'large',
}
+3 -1
View File
@@ -1,7 +1,9 @@
import * as ExpoConfig from '@expo/config';
import JsonFile from '@expo/json-file';
import JsonFileModule from '@expo/json-file';
import assert from 'assert';
const JsonFile = JsonFileModule.default;
export async function updateAppJsonConfigAsync(
{
projectDir,
@@ -2,8 +2,8 @@ import { Platform } from '@expo/eas-build-job';
import { CredentialsSource } from '@expo/eas-json';
import chalk from 'chalk';
import Log from '../../log';
import { requestedPlatformDisplayNames } from '../../platform';
import Log from '../../log.js';
import { requestedPlatformDisplayNames } from '../../platform.js';
export function logCredentialsSource(
credentialsSource: CredentialsSource,
@@ -3,15 +3,15 @@ import { Errors } from '@oclif/core';
import chalk from 'chalk';
import resolveFrom from 'resolve-from';
import { toAppPlatform } from '../../graphql/types/AppPlatform';
import Log, { learnMore } from '../../log';
import { appPlatformDisplayNames } from '../../platform';
import { resolveWorkflowAsync } from '../../project/workflow';
import { confirmAsync } from '../../prompts';
import { expoCommandAsync } from '../../utils/expoCli';
import { ProfileData } from '../../utils/profiles';
import { getVcsClient } from '../../vcs';
import { reviewAndCommitChangesAsync } from './repository';
import { toAppPlatform } from '../../graphql/types/AppPlatform.js';
import Log, { learnMore } from '../../log.js';
import { appPlatformDisplayNames } from '../../platform.js';
import { resolveWorkflowAsync } from '../../project/workflow.js';
import { confirmAsync } from '../../prompts.js';
import { expoCommandAsync } from '../../utils/expoCli.js';
import { ProfileData } from '../../utils/profiles.js';
import { getVcsClient } from '../../vcs/index.js';
import { reviewAndCommitChangesAsync } from './repository.js';
export async function ensureExpoDevClientInstalledForDevClientBuildsAsync({
projectDir,
@@ -4,10 +4,10 @@ import {
AppPlatform,
BuildFragment,
BuildStatus as GraphQLBuildStatus,
} from '../../graphql/generated';
import { appPlatformDisplayNames } from '../../platform';
import formatFields from '../../utils/formatFields';
import { getBuildLogsUrl } from './url';
} from '../../graphql/generated.js';
import { appPlatformDisplayNames } from '../../platform.js';
import formatFields from '../../utils/formatFields.js';
import { getBuildLogsUrl } from './url.js';
export function formatGraphQLBuild(build: BuildFragment): string {
const actor = getActorName(build);
@@ -11,11 +11,11 @@ import {
DistributionType,
EasBuildDeprecationInfo,
EasBuildDeprecationInfoType,
} from '../../graphql/generated';
import Log, { learnMore } from '../../log';
import { appPlatformDisplayNames, appPlatformEmojis } from '../../platform';
import { printJsonOnlyOutput } from '../../utils/json';
import { getBuildLogsUrl, getInternalDistributionInstallUrl } from './url';
} from '../../graphql/generated.js';
import Log, { learnMore } from '../../log.js';
import { appPlatformDisplayNames, appPlatformEmojis } from '../../platform.js';
import { printJsonOnlyOutput } from '../../utils/json.js';
import { getBuildLogsUrl, getInternalDistributionInstallUrl } from './url.js';
export function printLogsUrls(builds: BuildFragment[]): void {
if (builds.length === 1) {
@@ -4,13 +4,13 @@ import path from 'path';
import tar from 'tar';
import { v4 as uuidv4 } from 'uuid';
import Log from '../../log';
import { ora } from '../../ora';
import { confirmAsync, promptAsync } from '../../prompts';
import { formatBytes } from '../../utils/files';
import { getTmpDirectory } from '../../utils/paths';
import { endTimer, formatMilliseconds, startTimer } from '../../utils/timer';
import { getVcsClient } from '../../vcs';
import Log from '../../log.js';
import { ora } from '../../ora.js';
import { confirmAsync, promptAsync } from '../../prompts.js';
import { formatBytes } from '../../utils/files.js';
import { getTmpDirectory } from '../../utils/paths.js';
import { endTimer, formatMilliseconds, startTimer } from '../../utils/timer.js';
import { getVcsClient } from '../../vcs/index.js';
export async function maybeBailOnRepoStatusAsync(): Promise<void> {
if (!(await getVcsClient().isCommitRequiredAsync())) {
+15 -2
View File
@@ -1,7 +1,7 @@
import assert from 'assert';
import { getExpoApiBaseUrl, getExpoWebsiteBaseUrl } from '../../api';
import { AppPlatform, BuildFragment } from '../../graphql/generated';
import { getExpoApiBaseUrl, getExpoWebsiteBaseUrl } from '../../api.js';
import { AppPlatform, BuildFragment } from '../../graphql/generated.js';
export function getProjectDashboardUrl(accountName: string, projectName: string): string {
return new URL(
@@ -35,3 +35,16 @@ export function getInternalDistributionInstallUrl(build: BuildFragment): string
return build.artifacts.buildUrl;
}
export function getUpdateGroupUrl(
accountName: string,
projectName: string,
updateGroupId: string
): string {
return new URL(
`/accounts/${encodeURIComponent(accountName)}/projects/${encodeURIComponent(
projectName
)}/updates/${encodeURIComponent(updateGroupId)}`,
getExpoWebsiteBaseUrl()
).toString();
}
+4 -4
View File
@@ -1,11 +1,11 @@
import { ExpoConfig, getConfigFilePaths } from '@expo/config';
import chalk from 'chalk';
import nullthrows from 'nullthrows';
import semver from 'semver';
import Log from '../../log';
import { promptAsync } from '../../prompts';
import { updateAppJsonConfigAsync } from './appJson';
import Log from '../../log.js';
import { promptAsync } from '../../prompts.js';
import { nullthrows } from '../../utils/nullthrows.js';
import { updateAppJsonConfigAsync } from './appJson.js';
export function ensureStaticConfigExists(projectDir: string): void {
const paths = getConfigFilePaths(projectDir);
+3 -3
View File
@@ -2,9 +2,9 @@ import { Platform, Workflow } from '@expo/eas-build-job';
import fs from 'fs-extra';
import path from 'path';
import Log, { learnMore } from '../log';
import { getVcsClient } from '../vcs';
import { CommonContext } from './context';
import Log, { learnMore } from '../log.js';
import { getVcsClient } from '../vcs/index.js';
import { CommonContext } from './context.js';
export function checkNodeEnvVariable(ctx: CommonContext<Platform>): void {
if (ctx.buildProfile.env?.NODE_ENV === 'production') {
@@ -7,13 +7,13 @@ import {
flushAsync as flushAnalyticsAsync,
initAsync as initAnalyticsAsync,
logEvent,
} from '../analytics/rudderstackClient';
import { findProjectRootAsync } from '../project/projectUtils';
import { getUserAsync } from '../user/User';
import { ensureLoggedInAsync } from '../user/actions';
import { easCliVersion } from '../utils/easCli';
import { setVcsClient } from '../vcs';
import GitClient from '../vcs/clients/git';
} from '../analytics/rudderstackClient.js';
import { findProjectRootAsync } from '../project/projectUtils.js';
import { getUserAsync } from '../user/User.js';
import { ensureLoggedInAsync } from '../user/actions.js';
import { easCliVersion } from '../utils/easCli.js';
import GitClient from '../vcs/clients/git.js';
import { setVcsClient } from '../vcs/index.js';
export default abstract class EasCommand extends Command {
/**
@@ -1,12 +1,8 @@
import { asMock } from '../../__tests__/utils';
import { flushAsync, initAsync, logEvent } from '../../analytics/rudderstackClient';
import { jester as mockJester } from '../../credentials/__tests__/fixtures-constants';
import { getUserAsync } from '../../user/User';
import { ensureLoggedInAsync } from '../../user/actions';
import EasCommand from '../EasCommand';
import TestEasCommand from './TestEasCommand';
TestEasCommand.prototype.authValue = jest.fn().mockImplementation(() => true);
import { flushAsync, initAsync, logEvent } from '../../analytics/rudderstackClient.js';
import { jester as mockJester } from '../../credentials/__tests__/fixtures-constants.js';
import { getUserAsync } from '../../user/User.js';
import { ensureLoggedInAsync } from '../../user/actions.js';
import EasCommand from '../EasCommand.js';
jest.mock('../../user/User');
jest.mock('../../user/actions', () => ({ ensureLoggedInAsync: jest.fn() }));
@@ -32,17 +28,30 @@ afterAll(() => {
});
beforeEach(() => {
asMock(getUserAsync)
jest
.mocked(getUserAsync)
.mockReset()
.mockImplementation(() => mockJester);
asMock(ensureLoggedInAsync)
.mockImplementation(async () => mockJester);
jest
.mocked(ensureLoggedInAsync)
.mockReset()
.mockImplementation(() => mockJester);
asMock(initAsync).mockReset();
asMock(flushAsync).mockReset();
asMock(logEvent).mockReset();
.mockImplementation(async () => mockJester);
jest.mocked(initAsync).mockReset();
jest.mocked(flushAsync).mockReset();
jest.mocked(logEvent).mockReset();
});
const createTestEasCommand = (authValue: boolean): typeof EasCommand => {
class TestEasCommand extends EasCommand {
requiresAuthentication = authValue;
async runAsync(): Promise<void> {}
}
TestEasCommand.id = 'TestEasCommand'; // normally oclif will assign ids, but b/c this is located outside the commands folder it will not
return TestEasCommand;
};
describe(EasCommand.name, () => {
describe('without exceptions', () => {
// The first test in this suite should have an increased timeout
@@ -53,32 +62,36 @@ describe(EasCommand.name, () => {
// See https://github.com/oclif/command/blob/master/src/command.ts#L80
// and look for "Config.load"
it('ensures the user is logged in', async () => {
const TestEasCommand = createTestEasCommand(true);
await TestEasCommand.run();
expect(ensureLoggedInAsync).toHaveBeenCalled();
}, 15_000);
it('ensures the user data is read from cache', async () => {
asMock(TestEasCommand.prototype.authValue).mockImplementationOnce(() => false);
const TestEasCommand = createTestEasCommand(false);
await TestEasCommand.run();
expect(getUserAsync).toHaveReturnedWith(mockJester);
expect(jest.mocked(getUserAsync)).toBeCalledTimes(1);
expect(jest.mocked(ensureLoggedInAsync)).not.toBeCalled();
});
it('initializes analytics', async () => {
const TestEasCommand = createTestEasCommand(true);
await TestEasCommand.run();
expect(initAsync).toHaveBeenCalled();
});
it('flushes analytics', async () => {
const TestEasCommand = createTestEasCommand(true);
await TestEasCommand.run();
expect(flushAsync).toHaveBeenCalled();
});
it('logs events', async () => {
const TestEasCommand = createTestEasCommand(true);
await TestEasCommand.run();
expect(logEvent).toHaveBeenCalledWith('action', {
@@ -89,11 +102,12 @@ describe(EasCommand.name, () => {
describe('after exceptions', () => {
it('flushes analytics', async () => {
const TestEasCommand = createTestEasCommand(true);
try {
await TestEasCommand.run().then(() => {
throw new Error('foo');
});
} catch (error) {}
} catch {}
expect(flushAsync).toHaveBeenCalled();
});
@@ -1,13 +0,0 @@
import EasCommand from '../EasCommand';
export default class TestEasCommand extends EasCommand {
requiresAuthentication = this.authValue();
authValue(): boolean {
return false;
}
async runAsync(): Promise<void> {}
}
TestEasCommand.id = 'TestEasCommand'; // normally oclif will assign ids, but b/c this is located outside the commands folder it will not
@@ -1,6 +1,6 @@
import EasCommand from '../../commandUtils/EasCommand';
import Log from '../../log';
import { showLoginPromptAsync } from '../../user/actions';
import EasCommand from '../../commandUtils/EasCommand.js';
import Log from '../../log.js';
import { showLoginPromptAsync } from '../../user/actions.js';
export default class AccountLogin extends EasCommand {
static description = 'log in with your Expo account';
@@ -1,6 +1,6 @@
import EasCommand from '../../commandUtils/EasCommand';
import Log from '../../log';
import { logoutAsync } from '../../user/User';
import EasCommand from '../../commandUtils/EasCommand.js';
import Log from '../../log.js';
import { logoutAsync } from '../../user/User.js';
export default class AccountLogout extends EasCommand {
static description = 'log out';
@@ -1,8 +1,8 @@
import chalk from 'chalk';
import EasCommand from '../../commandUtils/EasCommand';
import Log from '../../log';
import { getActorDisplayName, getUserAsync } from '../../user/User';
import EasCommand from '../../commandUtils/EasCommand.js';
import Log from '../../log.js';
import { getActorDisplayName, getUserAsync } from '../../user/User.js';
export default class AccountView extends EasCommand {
static description = 'show the username you are logged in as';
+3 -3
View File
@@ -1,6 +1,6 @@
import EasCommand from '../commandUtils/EasCommand';
import Log from '../log';
import UserSettings from '../user/UserSettings';
import EasCommand from '../commandUtils/EasCommand.js';
import Log from '../log.js';
import UserSettings from '../user/UserSettings.js';
export default class AnalyticsView extends EasCommand {
static description = 'display or change analytics settings';
+11 -11
View File
@@ -1,24 +1,24 @@
import { getConfig } from '@expo/config';
import { Flags } from '@oclif/core';
import chalk from 'chalk';
import gql from 'graphql-tag';
import { gql } from 'graphql-tag';
import EasCommand from '../../commandUtils/EasCommand';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client';
import EasCommand from '../../commandUtils/EasCommand.js';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client.js';
import {
CreateUpdateBranchForAppMutation,
CreateUpdateBranchForAppMutationVariables,
UpdateBranch,
} from '../../graphql/generated';
import Log from '../../log';
} from '../../graphql/generated.js';
import Log from '../../log.js';
import { getExpoConfig } from '../../project/expoConfig.js';
import {
findProjectRootAsync,
getProjectFullNameAsync,
getProjectIdAsync,
} from '../../project/projectUtils';
import { promptAsync } from '../../prompts';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
import { getVcsClient } from '../../vcs';
} from '../../project/projectUtils.js';
import { promptAsync } from '../../prompts.js';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json.js';
import { getVcsClient } from '../../vcs/index.js';
export async function createUpdateBranchOnAppAsync({
appId,
@@ -79,7 +79,7 @@ export default class BranchCreate extends EasCommand {
}
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
const exp = getExpoConfig(projectDir);
const fullName = await getProjectFullNameAsync(exp);
const projectId = await getProjectIdAsync(exp);
+10 -10
View File
@@ -1,25 +1,25 @@
import { getConfig } from '@expo/config';
import { Flags } from '@oclif/core';
import chalk from 'chalk';
import gql from 'graphql-tag';
import { gql } from 'graphql-tag';
import EasCommand from '../../commandUtils/EasCommand';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client';
import EasCommand from '../../commandUtils/EasCommand.js';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client.js';
import {
DeleteUpdateBranchMutation,
DeleteUpdateBranchMutationVariables,
DeleteUpdateBranchResult,
GetBranchInfoQuery,
GetBranchInfoQueryVariables,
} from '../../graphql/generated';
import Log from '../../log';
} from '../../graphql/generated.js';
import Log from '../../log.js';
import { getExpoConfig } from '../../project/expoConfig.js';
import {
findProjectRootAsync,
getProjectFullNameAsync,
getProjectIdAsync,
} from '../../project/projectUtils';
import { promptAsync, toggleConfirmAsync } from '../../prompts';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
} from '../../project/projectUtils.js';
import { promptAsync, toggleConfirmAsync } from '../../prompts.js';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json.js';
async function getBranchInfoAsync({
appId,
@@ -103,7 +103,7 @@ export default class BranchDelete extends EasCommand {
}
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
const exp = getExpoConfig(projectDir);
const fullName = await getProjectFullNameAsync(exp);
const projectId = await getProjectIdAsync(exp);
+11 -11
View File
@@ -1,22 +1,22 @@
import { getConfig } from '@expo/config';
import { Flags } from '@oclif/core';
import chalk from 'chalk';
import CliTable from 'cli-table3';
import { print } from 'graphql';
import gql from 'graphql-tag';
import { gql } from 'graphql-tag';
import EasCommand from '../../commandUtils/EasCommand';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client';
import EasCommand from '../../commandUtils/EasCommand.js';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client.js';
import {
BranchesByAppQuery,
BranchesByAppQueryVariables,
UpdateBranchFragment,
} from '../../graphql/generated';
import { UpdateBranchFragmentNode } from '../../graphql/types/UpdateBranch';
import Log from '../../log';
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
import { UPDATE_COLUMNS, formatUpdate, getPlatformsForGroup } from '../../update/utils';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
} from '../../graphql/generated.js';
import { UpdateBranchFragmentNode } from '../../graphql/types/UpdateBranch.js';
import Log from '../../log.js';
import { getExpoConfig } from '../../project/expoConfig.js';
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils.js';
import { UPDATE_COLUMNS, formatUpdate, getPlatformsForGroup } from '../../update/utils.js';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json.js';
const BRANCHES_LIMIT = 10_000;
@@ -71,7 +71,7 @@ export default class BranchList extends EasCommand {
}
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
const exp = getExpoConfig(projectDir);
const projectId = await getProjectIdAsync(exp);
const branches = await listBranchesAsync({ projectId });
if (flags.json) {
@@ -1,4 +1,4 @@
import EasCommand from '../../commandUtils/EasCommand';
import EasCommand from '../../commandUtils/EasCommand.js';
export default class BranchPublish extends EasCommand {
static description = 'deprecated, use "eas update"';
+10 -10
View File
@@ -1,24 +1,24 @@
import { getConfig } from '@expo/config';
import { Flags } from '@oclif/core';
import chalk from 'chalk';
import gql from 'graphql-tag';
import { gql } from 'graphql-tag';
import EasCommand from '../../commandUtils/EasCommand';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client';
import EasCommand from '../../commandUtils/EasCommand.js';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client.js';
import {
EditUpdateBranchInput,
EditUpdateBranchMutation,
EditUpdateBranchMutationVariables,
UpdateBranch,
} from '../../graphql/generated';
import Log from '../../log';
} from '../../graphql/generated.js';
import Log from '../../log.js';
import { getExpoConfig } from '../../project/expoConfig.js';
import {
findProjectRootAsync,
getProjectFullNameAsync,
getProjectIdAsync,
} from '../../project/projectUtils';
import { promptAsync } from '../../prompts';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
} from '../../project/projectUtils.js';
import { promptAsync } from '../../prompts.js';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json.js';
async function renameUpdateBranchOnAppAsync({
appId,
@@ -78,7 +78,7 @@ export default class BranchRename extends EasCommand {
}
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
const exp = getExpoConfig(projectDir);
const fullName = await getProjectFullNameAsync(exp);
const projectId = await getProjectIdAsync(exp);
+11 -11
View File
@@ -1,17 +1,17 @@
import { getConfig } from '@expo/config';
import { Flags } from '@oclif/core';
import chalk from 'chalk';
import Table from 'cli-table3';
import EasCommand from '../../commandUtils/EasCommand';
import { UpdateQuery } from '../../graphql/queries/UpdateQuery';
import Log from '../../log';
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
import { promptAsync } from '../../prompts';
import { UPDATE_COLUMNS, formatUpdate, getPlatformsForGroup } from '../../update/utils';
import groupBy from '../../utils/expodash/groupBy';
import formatFields from '../../utils/formatFields';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
import EasCommand from '../../commandUtils/EasCommand.js';
import { UpdateQuery } from '../../graphql/queries/UpdateQuery.js';
import Log from '../../log.js';
import { getExpoConfig } from '../../project/expoConfig.js';
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils.js';
import { promptAsync } from '../../prompts.js';
import { UPDATE_COLUMNS, formatUpdate, getPlatformsForGroup } from '../../update/utils.js';
import groupBy from '../../utils/expodash/groupBy.js';
import formatFields from '../../utils/formatFields.js';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json.js';
export default class BranchView extends EasCommand {
static description = 'view a branch';
@@ -41,7 +41,7 @@ export default class BranchView extends EasCommand {
}
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
const exp = getExpoConfig(projectDir);
const projectId = await getProjectIdAsync(exp);
if (!name) {
+13 -13
View File
@@ -1,25 +1,25 @@
import { getConfig } from '@expo/config';
import chalk from 'chalk';
import gql from 'graphql-tag';
import { gql } from 'graphql-tag';
import EasCommand from '../../commandUtils/EasCommand';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client';
import EasCommand from '../../commandUtils/EasCommand.js';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client.js';
import {
Build,
BuildStatus,
CancelBuildMutation,
CancelBuildMutationVariables,
} from '../../graphql/generated';
import { BuildQuery } from '../../graphql/queries/BuildQuery';
import Log from '../../log';
import { ora } from '../../ora';
import { appPlatformEmojis } from '../../platform';
} from '../../graphql/generated.js';
import { BuildQuery } from '../../graphql/queries/BuildQuery.js';
import Log from '../../log.js';
import { ora } from '../../ora.js';
import { appPlatformEmojis } from '../../platform.js';
import { getExpoConfig } from '../../project/expoConfig.js';
import {
findProjectRootAsync,
getProjectFullNameAsync,
getProjectIdAsync,
} from '../../project/projectUtils';
import { confirmAsync, selectAsync } from '../../prompts';
} from '../../project/projectUtils.js';
import { confirmAsync, selectAsync } from '../../prompts.js';
async function cancelBuildAsync(buildId: string): Promise<Pick<Build, 'id' | 'status'>> {
const data = await withErrorHandlingAsync(
@@ -104,7 +104,7 @@ async function selectBuildToCancelAsync(
async function ensureBuildExistsAsync(buildId: string): Promise<void> {
try {
await BuildQuery.byIdAsync(buildId);
} catch (err) {
} catch {
throw new Error(`Couldn't find a build matching the id ${buildId}`);
}
}
@@ -118,7 +118,7 @@ export default class BuildCancel extends EasCommand {
const { BUILD_ID: buildIdFromArg } = (await this.parse(BuildCancel)).args;
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
const exp = getExpoConfig(projectDir);
const projectId = await getProjectIdAsync(exp);
const projectFullName = await getProjectFullNameAsync(exp);
@@ -1,19 +1,19 @@
import { getConfig } from '@expo/config';
import { Platform, Workflow } from '@expo/eas-build-job';
import { Flags } from '@oclif/core';
import chalk from 'chalk';
import { cleanUpOldEasBuildGradleScriptAsync } from '../../build/android/syncProjectConfiguration';
import { ensureProjectConfiguredAsync } from '../../build/configure';
import EasCommand from '../../commandUtils/EasCommand';
import Log, { learnMore } from '../../log';
import { RequestedPlatform } from '../../platform';
import { findProjectRootAsync, isExpoUpdatesInstalled } from '../../project/projectUtils';
import { resolveWorkflowAsync } from '../../project/workflow';
import { promptAsync } from '../../prompts';
import { syncUpdatesConfigurationAsync as syncAndroidUpdatesConfigurationAsync } from '../../update/android/UpdatesModule';
import { syncUpdatesConfigurationAsync as syncIosUpdatesConfigurationAsync } from '../../update/ios/UpdatesModule';
import { getVcsClient } from '../../vcs';
import { cleanUpOldEasBuildGradleScriptAsync } from '../../build/android/syncProjectConfiguration.js';
import { ensureProjectConfiguredAsync } from '../../build/configure.js';
import EasCommand from '../../commandUtils/EasCommand.js';
import Log, { learnMore } from '../../log.js';
import { RequestedPlatform } from '../../platform.js';
import { getExpoConfig } from '../../project/expoConfig.js';
import { findProjectRootAsync, isExpoUpdatesInstalled } from '../../project/projectUtils.js';
import { resolveWorkflowAsync } from '../../project/workflow.js';
import { promptAsync } from '../../prompts.js';
import { syncUpdatesConfigurationAsync as syncAndroidUpdatesConfigurationAsync } from '../../update/android/UpdatesModule.js';
import { syncUpdatesConfigurationAsync as syncIosUpdatesConfigurationAsync } from '../../update/ios/UpdatesModule.js';
import { getVcsClient } from '../../vcs/index.js';
export default class BuildConfigure extends EasCommand {
static description = 'configure the project to support EAS Build';
@@ -55,7 +55,7 @@ export default class BuildConfigure extends EasCommand {
// configure expo-updates
if (expoUpdatesIsInstalled) {
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
const exp = getExpoConfig(projectDir);
if ([RequestedPlatform.Android, RequestedPlatform.All].includes(platform)) {
const workflow = await resolveWorkflowAsync(projectDir, Platform.ANDROID);
+14 -80
View File
@@ -1,21 +1,13 @@
import { EasJsonReader } 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 { BuildFlags, runBuildAndSubmitAsync } from '../../build/runBuildAndSubmit';
import { ensureRepoIsCleanAsync, reviewAndCommitChangesAsync } from '../../build/utils/repository';
import EasCommand from '../../commandUtils/EasCommand';
import Log, { learnMore, link } from '../../log';
import { RequestedPlatform, selectRequestedPlatformAsync } from '../../platform';
import { findProjectRootAsync } from '../../project/projectUtils';
import { selectAsync } from '../../prompts';
import { easCliVersion } from '../../utils/easCli';
import { enableJsonOutput } from '../../utils/json';
import { getVcsClient, setVcsClient } from '../../vcs';
import GitClient from '../../vcs/clients/git';
import { BuildFlags, runBuildAndSubmitAsync } from '../../build/runBuildAndSubmit.js';
import { UserInputResourceClass } from '../../build/types.js';
import EasCommand from '../../commandUtils/EasCommand.js';
import Log from '../../log.js';
import { RequestedPlatform, selectRequestedPlatformAsync } from '../../platform.js';
import { findProjectRootAsync } from '../../project/projectUtils.js';
import { enableJsonOutput } from '../../utils/json.js';
interface RawBuildFlags {
platform?: string;
@@ -30,6 +22,7 @@ interface RawBuildFlags {
json: boolean;
'auto-submit': boolean;
'auto-submit-with-profile'?: string;
'resource-class'?: UserInputResourceClass;
}
export default class Build extends EasCommand {
@@ -88,6 +81,11 @@ export default class Build extends EasCommand {
helpValue: 'PROFILE_NAME',
exclusive: ['auto-submit'],
}),
'resource-class': Flags.enum({
options: Object.values(UserInputResourceClass),
hidden: true,
description: 'The instance type that will be used to run this build [experimental]',
}),
};
async runAsync(): Promise<void> {
@@ -98,7 +96,6 @@ export default class Build extends EasCommand {
const flags = await this.sanitizeFlagsAsync(rawFlags);
const projectDir = await findProjectRootAsync();
await handleDeprecatedEasJsonAsync(projectDir, flags.nonInteractive);
await runBuildAndSubmitAsync(projectDir, flags);
}
@@ -165,70 +162,7 @@ export default class Build extends EasCommand {
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,
};
}
}
export async function handleDeprecatedEasJsonAsync(
projectDir: string,
nonInteractive: boolean
): Promise<void> {
const easJsonPath = EasJsonReader.formatEasJsonPath(projectDir);
if (!(await fs.pathExists(easJsonPath))) {
return;
}
const easJsonReader = new EasJsonReader(projectDir);
const rawEasJson = await easJsonReader.readAsync();
if (rawEasJson?.cli) {
return;
}
if (nonInteractive) {
Log.warn(
`${
figures.warning
} Action required: the default behavior of EAS CLI has changed and your eas.json must be updated to remove ambiguity around which Git integration workflow to use. Refer to ${link(
'https://expo.fyi/eas-vcs-workflow'
)} for more information.`
);
Log.warn(
'This warning will become an error in an upcoming EAS CLI release. For now, we will proceed with the old default behavior to avoid disruption of your builds.'
);
setVcsClient(new GitClient());
return;
}
Log.log(
`${chalk.bold(
'eas-cli@>=0.34.0 no longer requires that you commit changes to Git before starting a build.'
)} ${learnMore('https://expo.fyi/eas-vcs-workflow')}`
);
Log.log(
`If you want to continue using the Git integration, you can opt in with ${chalk.bold(
'cli.requireCommit'
)} in ${chalk.bold('eas.json')} or with the following prompt.`
);
Log.newLine();
const mode = await selectAsync('Select your preferred Git integration', [
{ title: 'Require changes to be committed in Git (old default)', value: 'requireCommit' },
{ title: 'Allow builds with dirty Git working tree (new default)', value: 'noCommit' },
]);
if (mode === 'requireCommit') {
setVcsClient(new GitClient());
await ensureRepoIsCleanAsync(nonInteractive);
}
rawEasJson.cli =
mode === 'requireCommit'
? { version: `>= ${easCliVersion}`, requireCommit: true }
: { version: `>= ${easCliVersion}` };
await fs.writeJSON(easJsonPath, rawEasJson, { spaces: 2 });
Log.withTick('Updated eas.json');
if (mode === 'requireCommit') {
await getVcsClient().trackFileAsync(easJsonPath);
await reviewAndCommitChangesAsync('Set cli.requireCommit to true in eas.json', {
nonInteractive,
});
}
}
@@ -4,14 +4,14 @@ import fs from 'fs-extra';
import path from 'path';
import { v4 as uuidv4 } from 'uuid';
import { runBuildAndSubmitAsync } from '../../build/runBuildAndSubmit';
import EasCommand from '../../commandUtils/EasCommand';
import Log from '../../log';
import { ora } from '../../ora';
import { RequestedPlatform } from '../../platform';
import { findProjectRootAsync } from '../../project/projectUtils';
import { getTmpDirectory } from '../../utils/paths';
import { getVcsClient } from '../../vcs';
import { runBuildAndSubmitAsync } from '../../build/runBuildAndSubmit.js';
import EasCommand from '../../commandUtils/EasCommand.js';
import Log from '../../log.js';
import { ora } from '../../ora.js';
import { RequestedPlatform } from '../../platform.js';
import { findProjectRootAsync } from '../../project/projectUtils.js';
import { getTmpDirectory } from '../../utils/paths.js';
import { getVcsClient } from '../../vcs/index.js';
enum InspectStage {
ARCHIVE = 'archive',
@@ -102,7 +102,7 @@ export default class BuildInspect extends EasCommand {
if (!flags.verbose) {
Log.log(chalk.green('Build successful'));
}
} catch (err) {
} catch {
if (!flags.verbose) {
Log.error('Build failed');
Log.error(`Re-run this command with ${chalk.bold('--verbose')} flag to see the logs`);
+12 -12
View File
@@ -1,25 +1,25 @@
import { getConfig } from '@expo/config';
import { Flags } from '@oclif/core';
import chalk from 'chalk';
import { BuildDistributionType, BuildStatus } from '../../build/types';
import { formatGraphQLBuild } from '../../build/utils/formatBuild';
import EasCommand from '../../commandUtils/EasCommand';
import { BuildDistributionType, BuildStatus } from '../../build/types.js';
import { formatGraphQLBuild } from '../../build/utils/formatBuild.js';
import EasCommand from '../../commandUtils/EasCommand.js';
import {
AppPlatform,
DistributionType,
BuildStatus as GraphQLBuildStatus,
} from '../../graphql/generated';
import { BuildQuery } from '../../graphql/queries/BuildQuery';
import Log from '../../log';
import { ora } from '../../ora';
import { RequestedPlatform } from '../../platform';
} from '../../graphql/generated.js';
import { BuildQuery } from '../../graphql/queries/BuildQuery.js';
import Log from '../../log.js';
import { ora } from '../../ora.js';
import { RequestedPlatform } from '../../platform.js';
import { getExpoConfig } from '../../project/expoConfig.js';
import {
findProjectRootAsync,
getProjectFullNameAsync,
getProjectIdAsync,
} from '../../project/projectUtils';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
} from '../../project/projectUtils.js';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json.js';
export default class BuildList extends EasCommand {
static description = 'list all builds for your project';
@@ -77,7 +77,7 @@ export default class BuildList extends EasCommand {
const graphqlBuildDistribution = toGraphQLBuildDistribution(buildDistribution);
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
const exp = getExpoConfig(projectDir);
const projectId = await getProjectIdAsync(exp);
const projectName = await getProjectFullNameAsync(exp);
+10 -10
View File
@@ -1,18 +1,18 @@
import { getConfig } from '@expo/config';
import { Flags } from '@oclif/core';
import { formatGraphQLBuild } from '../../build/utils/formatBuild';
import EasCommand from '../../commandUtils/EasCommand';
import { BuildFragment } from '../../graphql/generated';
import { BuildQuery } from '../../graphql/queries/BuildQuery';
import Log from '../../log';
import { ora } from '../../ora';
import { formatGraphQLBuild } from '../../build/utils/formatBuild.js';
import EasCommand from '../../commandUtils/EasCommand.js';
import { BuildFragment } from '../../graphql/generated.js';
import { BuildQuery } from '../../graphql/queries/BuildQuery.js';
import Log from '../../log.js';
import { ora } from '../../ora.js';
import { getExpoConfig } from '../../project/expoConfig.js';
import {
findProjectRootAsync,
getProjectFullNameAsync,
getProjectIdAsync,
} from '../../project/projectUtils';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
} from '../../project/projectUtils.js';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json.js';
export default class BuildView extends EasCommand {
static description = 'view a build for your project';
@@ -35,7 +35,7 @@ export default class BuildView extends EasCommand {
}
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
const exp = getExpoConfig(projectDir);
const projectId = await getProjectIdAsync(exp);
const projectName = await getProjectFullNameAsync(exp);
+13 -13
View File
@@ -1,25 +1,25 @@
import { getConfig } from '@expo/config';
import { Flags } from '@oclif/core';
import chalk from 'chalk';
import gql from 'graphql-tag';
import { gql } from 'graphql-tag';
import EasCommand from '../../commandUtils/EasCommand';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client';
import EasCommand from '../../commandUtils/EasCommand.js';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client.js';
import {
CreateUpdateChannelOnAppMutation,
CreateUpdateChannelOnAppMutationVariables,
} from '../../graphql/generated';
import { BranchQuery } from '../../graphql/queries/BranchQuery';
import Log from '../../log';
} from '../../graphql/generated.js';
import { BranchQuery } from '../../graphql/queries/BranchQuery.js';
import Log from '../../log.js';
import { getExpoConfig } from '../../project/expoConfig.js';
import {
findProjectRootAsync,
getProjectFullNameAsync,
getProjectIdAsync,
} from '../../project/projectUtils';
import { promptAsync } from '../../prompts';
import formatFields from '../../utils/formatFields';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
import { createUpdateBranchOnAppAsync } from '../branch/create';
} from '../../project/projectUtils.js';
import { promptAsync } from '../../prompts.js';
import formatFields from '../../utils/formatFields.js';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json.js';
import { createUpdateBranchOnAppAsync } from '../branch/create.js';
export async function createUpdateChannelOnAppAsync({
appId,
@@ -88,7 +88,7 @@ export default class ChannelCreate extends EasCommand {
}
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
const exp = getExpoConfig(projectDir);
const projectId = await getProjectIdAsync(exp);
if (!channelName) {
+10 -10
View File
@@ -1,24 +1,24 @@
import { getConfig } from '@expo/config';
import { Flags } from '@oclif/core';
import gql from 'graphql-tag';
import { gql } from 'graphql-tag';
import EasCommand from '../../commandUtils/EasCommand';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client';
import EasCommand from '../../commandUtils/EasCommand.js';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client.js';
import {
DeleteUpdateChannelMutation,
DeleteUpdateChannelMutationVariables,
DeleteUpdateChannelResult,
GetChannelInfoQuery,
GetChannelInfoQueryVariables,
} from '../../graphql/generated';
import Log from '../../log';
} from '../../graphql/generated.js';
import Log from '../../log.js';
import { getExpoConfig } from '../../project/expoConfig.js';
import {
findProjectRootAsync,
getProjectFullNameAsync,
getProjectIdAsync,
} from '../../project/projectUtils';
import { promptAsync, toggleConfirmAsync } from '../../prompts';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
} from '../../project/projectUtils.js';
import { promptAsync, toggleConfirmAsync } from '../../prompts.js';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json.js';
export default class ChannelDelete extends EasCommand {
static hidden = true;
@@ -55,7 +55,7 @@ export default class ChannelDelete extends EasCommand {
}
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
const exp = getExpoConfig(projectDir);
const fullName = await getProjectFullNameAsync(exp);
const projectId = await getProjectIdAsync(exp);
+11 -11
View File
@@ -1,10 +1,9 @@
import { getConfig } from '@expo/config';
import { Flags } from '@oclif/core';
import chalk from 'chalk';
import gql from 'graphql-tag';
import { gql } from 'graphql-tag';
import EasCommand from '../../commandUtils/EasCommand';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client';
import EasCommand from '../../commandUtils/EasCommand.js';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client.js';
import {
GetChannelByNameToEditQuery,
GetChannelByNameToEditQueryVariables,
@@ -12,12 +11,13 @@ import {
UpdateChannel,
UpdateChannelBranchMappingMutation,
UpdateChannelBranchMappingMutationVariables,
} from '../../graphql/generated';
import { BranchQuery } from '../../graphql/queries/BranchQuery';
import Log from '../../log';
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
import { promptAsync } from '../../prompts';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
} from '../../graphql/generated.js';
import { BranchQuery } from '../../graphql/queries/BranchQuery.js';
import Log from '../../log.js';
import { getExpoConfig } from '../../project/expoConfig.js';
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils.js';
import { promptAsync } from '../../prompts.js';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json.js';
async function getChannelByNameForAppAsync({
appId,
@@ -120,7 +120,7 @@ export default class ChannelEdit extends EasCommand {
}
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
const exp = getExpoConfig(projectDir);
const projectId = await getProjectIdAsync(exp);
const channelName = args.name ?? (await promptForChannelAsync());
+11 -11
View File
@@ -1,18 +1,18 @@
import { getConfig } from '@expo/config';
import { Flags } from '@oclif/core';
import gql from 'graphql-tag';
import { gql } from 'graphql-tag';
import EasCommand from '../../commandUtils/EasCommand';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client';
import EasCommand from '../../commandUtils/EasCommand.js';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client.js';
import {
GetAllChannelsForAppQuery,
GetAllChannelsForAppQueryVariables,
} from '../../graphql/generated';
import Log from '../../log';
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
import formatFields from '../../utils/formatFields';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
import { logChannelDetails } from './view';
} from '../../graphql/generated.js';
import Log from '../../log.js';
import { getExpoConfig } from '../../project/expoConfig.js';
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils.js';
import formatFields from '../../utils/formatFields.js';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json.js';
import { logChannelDetails } from './view.js';
const CHANNEL_LIMIT = 10_000;
@@ -85,7 +85,7 @@ export default class ChannelList extends EasCommand {
}
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
const exp = getExpoConfig(projectDir);
const projectId = await getProjectIdAsync(exp);
const getAllUpdateChannelForAppResult = await getAllUpdateChannelForAppAsync({
@@ -1,21 +1,21 @@
import { getConfig } from '@expo/config';
import { Flags } from '@oclif/core';
import chalk from 'chalk';
import EasCommand from '../../commandUtils/EasCommand';
import { GetChannelByNameForAppQuery, UpdateBranch } from '../../graphql/generated';
import { BranchQuery } from '../../graphql/queries/BranchQuery';
import { ChannelQuery } from '../../graphql/queries/ChannelQuery';
import Log from '../../log';
import EasCommand from '../../commandUtils/EasCommand.js';
import { GetChannelByNameForAppQuery, UpdateBranch } from '../../graphql/generated.js';
import { BranchQuery } from '../../graphql/queries/BranchQuery.js';
import { ChannelQuery } from '../../graphql/queries/ChannelQuery.js';
import Log from '../../log.js';
import { getExpoConfig } from '../../project/expoConfig.js';
import {
findProjectRootAsync,
getProjectFullNameAsync,
getProjectIdAsync,
} from '../../project/projectUtils';
import { promptAsync, selectAsync } from '../../prompts';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
import { updateChannelBranchMappingAsync } from './edit';
import { BranchMapping, getBranchMapping } from './view';
} from '../../project/projectUtils.js';
import { promptAsync, selectAsync } from '../../prompts.js';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json.js';
import { updateChannelBranchMappingAsync } from './edit.js';
import { BranchMapping, getBranchMapping } from './view.js';
async function promptForRolloutPercentAsync({
promptMessage,
@@ -344,7 +344,7 @@ export default class ChannelRollout extends EasCommand {
}
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
const exp = getExpoConfig(projectDir);
const fullName = await getProjectFullNameAsync(exp);
const projectId = await getProjectIdAsync(exp);
+11 -11
View File
@@ -1,22 +1,22 @@
import { getConfig } from '@expo/config';
import { Flags } from '@oclif/core';
import assert from 'assert';
import chalk from 'chalk';
import Table from 'cli-table3';
import EasCommand from '../../commandUtils/EasCommand';
import { ChannelQuery } from '../../graphql/queries/ChannelQuery';
import Log from '../../log';
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
import { promptAsync } from '../../prompts';
import EasCommand from '../../commandUtils/EasCommand.js';
import { ChannelQuery } from '../../graphql/queries/ChannelQuery.js';
import Log from '../../log.js';
import { getExpoConfig } from '../../project/expoConfig.js';
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils.js';
import { promptAsync } from '../../prompts.js';
import {
FormatUpdateParameter,
UPDATE_COLUMNS,
formatUpdate,
getPlatformsForGroup,
} from '../../update/utils';
import formatFields from '../../utils/formatFields';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
} from '../../update/utils.js';
import formatFields from '../../utils/formatFields.js';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json.js';
export type BranchMapping = {
version: number;
@@ -45,7 +45,7 @@ export function getBranchMapping(branchMappingString?: string): {
let branchMapping: BranchMapping;
try {
branchMapping = JSON.parse(branchMappingString);
} catch (e) {
} catch {
throw new Error(`Could not parse branchMapping string into a JSON: "${branchMappingString}"`);
}
assert(branchMapping, 'Branch Mapping must be defined.');
@@ -165,7 +165,7 @@ export default class ChannelView extends EasCommand {
}
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
const exp = getExpoConfig(projectDir);
const projectId = await getProjectIdAsync(exp);
if (!channelName) {
+7 -9
View File
@@ -4,14 +4,13 @@ import { EasJsonReader } from '@expo/eas-json';
import { Flags } from '@oclif/core';
import chalk from 'chalk';
import EasCommand from '../commandUtils/EasCommand';
import { toAppPlatform } from '../graphql/types/AppPlatform';
import Log from '../log';
import { appPlatformEmojis } from '../platform';
import { getExpoConfig } from '../project/expoConfig';
import { findProjectRootAsync } from '../project/projectUtils';
import { selectAsync } from '../prompts';
import { handleDeprecatedEasJsonAsync } from './build';
import EasCommand from '../commandUtils/EasCommand.js';
import { toAppPlatform } from '../graphql/types/AppPlatform.js';
import Log from '../log.js';
import { appPlatformEmojis } from '../platform.js';
import { getExpoConfig } from '../project/expoConfig.js';
import { findProjectRootAsync } from '../project/projectUtils.js';
import { selectAsync } from '../prompts.js';
export default class Config extends EasCommand {
static description = 'display project configuration (app.json + eas.json)';
@@ -31,7 +30,6 @@ export default class Config extends EasCommand {
};
const projectDir = await findProjectRootAsync();
await handleDeprecatedEasJsonAsync(projectDir, false);
const reader = new EasJsonReader(projectDir);
const profileName =
+2 -2
View File
@@ -1,5 +1,5 @@
import EasCommand from '../commandUtils/EasCommand';
import { SelectPlatform } from '../credentials/manager/SelectPlatform';
import EasCommand from '../commandUtils/EasCommand.js';
import { SelectPlatform } from '../credentials/manager/SelectPlatform.js';
export default class Credentials extends EasCommand {
static description = 'manage credentials';
@@ -1,8 +1,8 @@
import EasCommand from '../../commandUtils/EasCommand';
import AppStoreApi from '../../credentials/ios/appstore/AppStoreApi';
import { createContextAsync } from '../../devices/context';
import DeviceManager from '../../devices/manager';
import { ensureLoggedInAsync } from '../../user/actions';
import EasCommand from '../../commandUtils/EasCommand.js';
import AppStoreApi from '../../credentials/ios/appstore/AppStoreApi.js';
import { createContextAsync } from '../../devices/context.js';
import DeviceManager from '../../devices/manager.js';
import { ensureLoggedInAsync } from '../../user/actions.js';
export default class DeviceCreate extends EasCommand {
static description = 'register new Apple Devices to use for internal distribution';
+20 -15
View File
@@ -1,24 +1,29 @@
import { Device, DeviceStatus } from '@expo/apple-utils';
import { getConfig } from '@expo/config';
import AppleUtils from '@expo/apple-utils';
import { Flags } from '@oclif/core';
import assert from 'assert';
import EasCommand from '../../commandUtils/EasCommand';
import { chooseDevicesToDeleteAsync } from '../../credentials/ios/actions/DeviceUtils';
import { AppleDeviceMutation } from '../../credentials/ios/api/graphql/mutations/AppleDeviceMutation';
import EasCommand from '../../commandUtils/EasCommand.js';
import { chooseDevicesToDeleteAsync } from '../../credentials/ios/actions/DeviceUtils.js';
import { AppleDeviceMutation } from '../../credentials/ios/api/graphql/mutations/AppleDeviceMutation.js';
import {
AppleDeviceQuery,
AppleDeviceQueryResult,
AppleDevicesByTeamIdentifierQueryResult,
} from '../../credentials/ios/api/graphql/queries/AppleDeviceQuery';
import { AppleTeamQuery } from '../../credentials/ios/api/graphql/queries/AppleTeamQuery';
import { authenticateAsync, getRequestContext } from '../../credentials/ios/appstore/authenticate';
import formatDevice from '../../devices/utils/formatDevice';
import { AppleDevice, Maybe } from '../../graphql/generated';
import Log from '../../log';
import { ora } from '../../ora';
import { findProjectRootAsync, getProjectAccountNameAsync } from '../../project/projectUtils';
import { promptAsync, toggleConfirmAsync } from '../../prompts';
} from '../../credentials/ios/api/graphql/queries/AppleDeviceQuery.js';
import { AppleTeamQuery } from '../../credentials/ios/api/graphql/queries/AppleTeamQuery.js';
import {
authenticateAsync,
getRequestContext,
} from '../../credentials/ios/appstore/authenticate.js';
import formatDevice from '../../devices/utils/formatDevice.js';
import { AppleDevice, Maybe } from '../../graphql/generated.js';
import Log from '../../log.js';
import { ora } from '../../ora.js';
import { getExpoConfig } from '../../project/expoConfig.js';
import { findProjectRootAsync, getProjectAccountNameAsync } from '../../project/projectUtils.js';
import { promptAsync, toggleConfirmAsync } from '../../prompts.js';
const { Device, DeviceStatus } = AppleUtils;
export default class DeviceDelete extends EasCommand {
static description = 'remove a registered device from your account';
@@ -34,7 +39,7 @@ export default class DeviceDelete extends EasCommand {
} = await this.parse(DeviceDelete);
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
const exp = getExpoConfig(projectDir);
const accountName = await getProjectAccountNameAsync(exp);
if (!appleTeamIdentifier) {
+10 -10
View File
@@ -1,16 +1,16 @@
import { getConfig } from '@expo/config';
import { Flags } from '@oclif/core';
import assert from 'assert';
import chalk from 'chalk';
import EasCommand from '../../commandUtils/EasCommand';
import { AppleDeviceQuery } from '../../credentials/ios/api/graphql/queries/AppleDeviceQuery';
import { AppleTeamQuery } from '../../credentials/ios/api/graphql/queries/AppleTeamQuery';
import formatDevice from '../../devices/utils/formatDevice';
import Log from '../../log';
import { Ora, ora } from '../../ora';
import { findProjectRootAsync, getProjectAccountNameAsync } from '../../project/projectUtils';
import { promptAsync } from '../../prompts';
import EasCommand from '../../commandUtils/EasCommand.js';
import { AppleDeviceQuery } from '../../credentials/ios/api/graphql/queries/AppleDeviceQuery.js';
import { AppleTeamQuery } from '../../credentials/ios/api/graphql/queries/AppleTeamQuery.js';
import formatDevice from '../../devices/utils/formatDevice.js';
import Log from '../../log.js';
import { Ora, ora } from '../../ora.js';
import { getExpoConfig } from '../../project/expoConfig.js';
import { findProjectRootAsync, getProjectAccountNameAsync } from '../../project/projectUtils.js';
import { promptAsync } from '../../prompts.js';
export default class BuildList extends EasCommand {
static description = 'list all registered devices for your account';
@@ -23,7 +23,7 @@ export default class BuildList extends EasCommand {
let appleTeamIdentifier = (await this.parse(BuildList)).flags['apple-team-id'];
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
const exp = getExpoConfig(projectDir);
const accountName = await getProjectAccountNameAsync(exp);
let spinner: Ora;
+8 -9
View File
@@ -1,11 +1,10 @@
import { getConfig } from '@expo/config';
import EasCommand from '../../commandUtils/EasCommand';
import { AppleDeviceQuery } from '../../credentials/ios/api/graphql/queries/AppleDeviceQuery';
import formatDevice from '../../devices/utils/formatDevice';
import Log from '../../log';
import { ora } from '../../ora';
import { findProjectRootAsync, getProjectAccountNameAsync } from '../../project/projectUtils';
import EasCommand from '../../commandUtils/EasCommand.js';
import { AppleDeviceQuery } from '../../credentials/ios/api/graphql/queries/AppleDeviceQuery.js';
import formatDevice from '../../devices/utils/formatDevice.js';
import Log from '../../log.js';
import { ora } from '../../ora.js';
import { getExpoConfig } from '../../project/expoConfig.js';
import { findProjectRootAsync, getProjectAccountNameAsync } from '../../project/projectUtils.js';
export default class DeviceView extends EasCommand {
static description = 'view a device for your project';
@@ -30,7 +29,7 @@ If you are not sure what is the UDID of the device you are looking for, run:
}
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
const exp = getExpoConfig(projectDir);
const accountName = await getProjectAccountNameAsync(exp);
const spinner = ora().start(`Fetching device details for ${UDID}…`);
+5 -5
View File
@@ -1,11 +1,11 @@
import { Platform } from '@expo/eas-build-job';
import envinfo from 'envinfo';
import EasCommand from '../commandUtils/EasCommand';
import Log from '../log';
import { findProjectRootAsync } from '../project/projectUtils';
import { resolveWorkflowAsync } from '../project/workflow';
import { easCliVersion } from '../utils/easCli';
import EasCommand from '../commandUtils/EasCommand.js';
import Log from '../log.js';
import { findProjectRootAsync } from '../project/projectUtils.js';
import { resolveWorkflowAsync } from '../project/workflow.js';
import { easCliVersion } from '../utils/easCli.js';
export default class Diagnostics extends EasCommand {
static description = 'display environment info';
@@ -0,0 +1,64 @@
import { getConfig } from '@expo/config';
import { Flags } from '@oclif/core';
import chalk from 'chalk';
import path from 'path';
import { ensureProjectConfiguredAsync } from '../../build/configure.js';
import EasCommand from '../../commandUtils/EasCommand.js';
import { CredentialsContext } from '../../credentials/context.js';
import Log, { learnMore } from '../../log.js';
import { createMetadataContextAsync } from '../../metadata/context.js';
import { downloadMetadataAsync } from '../../metadata/download.js';
import { handleMetadataError } from '../../metadata/errors.js';
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils.js';
import { ensureLoggedInAsync } from '../../user/actions.js';
export default class MetadataPull extends EasCommand {
static description = 'generate the local store configuration from the app stores';
static flags = {
profile: Flags.string({
description:
'Name of the submit profile from eas.json. Defaults to "production" if defined in eas.json.',
}),
};
async runAsync(): Promise<void> {
Log.warn('EAS Metadata is in beta and subject to breaking changes.');
const { flags } = await this.parse(MetadataPull);
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
await getProjectIdAsync(exp);
await ensureProjectConfiguredAsync({ projectDir, nonInteractive: false });
const credentialsCtx = new CredentialsContext({
exp,
projectDir,
user: await ensureLoggedInAsync(),
nonInteractive: false,
});
const metadataCtx = await createMetadataContextAsync({
credentialsCtx,
projectDir,
exp,
profileName: flags.profile,
});
try {
const filePath = await downloadMetadataAsync(metadataCtx);
const relativePath = path.relative(process.cwd(), filePath);
Log.addNewLineIfNone();
Log.log(`🎉 Your store configuration is ready.
- Update the ${chalk.bold(relativePath)} file to prepare the app information.
- Run ${chalk.bold('eas submit')} or manually upload a new app version to the app stores.
- Once the app is uploaded, run ${chalk.bold('eas metadata:push')} to sync the store configuration.
- ${learnMore('https://docs.expo.dev/eas-metadata/introduction/')}`);
} catch (error: any) {
handleMetadataError(error);
}
}
}
@@ -0,0 +1,57 @@
import { getConfig } from '@expo/config';
import { Flags } from '@oclif/core';
import { ensureProjectConfiguredAsync } from '../../build/configure.js';
import EasCommand from '../../commandUtils/EasCommand.js';
import { CredentialsContext } from '../../credentials/context.js';
import Log, { learnMore } from '../../log.js';
import { createMetadataContextAsync } from '../../metadata/context.js';
import { handleMetadataError } from '../../metadata/errors.js';
import { uploadMetadataAsync } from '../../metadata/upload.js';
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils.js';
import { ensureLoggedInAsync } from '../../user/actions.js';
export default class MetadataPush extends EasCommand {
static description = 'sync the local store configuration to the app stores';
static flags = {
profile: Flags.string({
description:
'Name of the submit profile from eas.json. Defaults to "production" if defined in eas.json.',
}),
};
async runAsync(): Promise<void> {
Log.warn('EAS Metadata is in beta and subject to breaking changes.');
const { flags } = await this.parse(MetadataPush);
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
await getProjectIdAsync(exp);
await ensureProjectConfiguredAsync({ projectDir, nonInteractive: false });
const credentialsCtx = new CredentialsContext({
exp,
projectDir,
user: await ensureLoggedInAsync(),
nonInteractive: false,
});
const metadataCtx = await createMetadataContextAsync({
credentialsCtx,
projectDir,
exp,
profileName: flags.profile,
});
try {
const { appleLink } = await uploadMetadataAsync(metadataCtx);
Log.addNewLineIfNone();
Log.log(`🎉 Store configuration is synced with the app stores.
${learnMore(appleLink, { learnMoreMessage: 'See the changes in App Store Connect' })}`);
} catch (error: any) {
handleMetadataError(error);
}
}
}
@@ -1,12 +1,12 @@
import { getConfig } from '@expo/config';
import gql from 'graphql-tag';
import { gql } from 'graphql-tag';
import EasCommand from '../../commandUtils/EasCommand';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client';
import { AppInfoQuery, AppInfoQueryVariables } from '../../graphql/generated';
import Log from '../../log';
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
import formatFields from '../../utils/formatFields';
import EasCommand from '../../commandUtils/EasCommand.js';
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client.js';
import { AppInfoQuery, AppInfoQueryVariables } from '../../graphql/generated.js';
import Log from '../../log.js';
import { getExpoConfig } from '../../project/expoConfig.js';
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils.js';
import formatFields from '../../utils/formatFields.js';
async function projectInfoByIdAsync(appId: string): Promise<AppInfoQuery> {
const data = await withErrorHandlingAsync(
@@ -36,7 +36,7 @@ export default class ProjectInfo extends EasCommand {
async runAsync(): Promise<void> {
const projectDir = await findProjectRootAsync();
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
const exp = getExpoConfig(projectDir);
const projectId = await getProjectIdAsync(exp);
const { app } = await projectInfoByIdAsync(projectId);
if (!app) {
Loaded 100 of 532 files, more files were not shown because too many files have changed in this diff. Show more