mirror of
https://github.com/expo/eas-cli.git
synced 2026-11-14 10:08:06 -10:00
Compare commits
86
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd7a3912c6 | ||
|
|
77ac0550a9 | ||
|
|
f9978baba2 | ||
|
|
2023f6161d | ||
|
|
a4f35466c3 | ||
|
|
5f73b0a2d7 | ||
|
|
d194f18b8e | ||
|
|
17e1a145e8 | ||
|
|
7ebb547fd9 | ||
|
|
6eca9ad564 | ||
|
|
229f00a8ed | ||
|
|
2bbf7f2b6d | ||
|
|
d578abc69a | ||
|
|
89253f5767 | ||
|
|
dd5afd354a | ||
|
|
bdcc768354 | ||
|
|
9cd2bafac5 | ||
|
|
69515ab47b | ||
|
|
ac5f7ab186 | ||
|
|
265c7eacc5 | ||
|
|
98229581ca | ||
|
|
a718fd10d3 | ||
|
|
78a63b8ca1 | ||
|
|
7487f413de | ||
|
|
da5f4e644a | ||
|
|
be38117012 | ||
|
|
8f3314f188 | ||
|
|
31b6cc9ab6 | ||
|
|
04a8b08f59 | ||
|
|
8bce9b19b2 | ||
|
|
d3d6d41f9f | ||
|
|
0534328dfc | ||
|
|
d0b9af2553 | ||
|
|
80674a3451 | ||
|
|
41b48a80be | ||
|
|
3d5b77a263 | ||
|
|
fa25d259d9 | ||
|
|
26596f32e9 | ||
|
|
031c610d58 | ||
|
|
fcb5beccb4 | ||
|
|
3003a712f6 | ||
|
|
e89f030c29 | ||
|
|
3e224f9583 | ||
|
|
db338b2b78 | ||
|
|
971c8e4010 | ||
|
|
df64a59354 | ||
|
|
e5d80fcb6d | ||
|
|
4088ea3e43 | ||
|
|
edd42186d9 | ||
|
|
e6ba63cfd0 | ||
|
|
7b60901bb1 | ||
|
|
a551e9010a | ||
|
|
95441798ed | ||
|
|
814f863a63 | ||
|
|
283f086b25 | ||
|
|
7da01333c6 | ||
|
|
c057eaa098 | ||
|
|
968fdd221c | ||
|
|
6d28e0eecc | ||
|
|
a2b4d2dbd2 | ||
|
|
660c996602 | ||
|
|
35ede265ed | ||
|
|
cf02f075d7 | ||
|
|
a2027eabd2 | ||
|
|
4ef239c59c | ||
|
|
3610eee2b5 | ||
|
|
54ae94f532 | ||
|
|
c68bf3e26f | ||
|
|
940e3f6d40 | ||
|
|
4c6226b90b | ||
|
|
1341bb18d1 | ||
|
|
beac65ce53 | ||
|
|
a8cc54d409 | ||
|
|
6a639bd556 | ||
|
|
dde9685b38 | ||
|
|
5b3a76a5b5 | ||
|
|
513e09157b | ||
|
|
69a939c635 | ||
|
|
58156545d0 | ||
|
|
8a52b5c401 | ||
|
|
14d4c7b234 | ||
|
|
fd17c96b3b | ||
|
|
833a5465c5 | ||
|
|
f0c958e58b | ||
|
|
607838c8e1 | ||
|
|
34ecd38304 |
No files matched your search
@@ -37,7 +37,7 @@ body:
|
|||||||
required: true
|
required: true
|
||||||
attributes:
|
attributes:
|
||||||
label: Environment
|
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
|
- type: textarea
|
||||||
validations:
|
validations:
|
||||||
required: false
|
required: false
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: '16'
|
node-version: 18
|
||||||
- name: Checkout Pull Request
|
- name: Checkout Pull Request
|
||||||
run: hub pr checkout ${{ github.event.issue.number }}
|
run: hub pr checkout ${{ github.event.issue.number }}
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -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'
|
||||||
|
})
|
||||||
@@ -27,7 +27,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: '16'
|
node-version: 18
|
||||||
- run: yarn install --frozen-lockfile --check-files
|
- run: yarn install --frozen-lockfile --check-files
|
||||||
- run: yarn build
|
- run: yarn build
|
||||||
- name: Build tarballs
|
- name: Build tarballs
|
||||||
@@ -68,7 +68,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: '16'
|
node-version: 18
|
||||||
- run: yarn install --frozen-lockfile --check-files
|
- run: yarn install --frozen-lockfile --check-files
|
||||||
- run: yarn build
|
- run: yarn build
|
||||||
- name: Build tarballs
|
- name: Build tarballs
|
||||||
@@ -96,7 +96,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: '16'
|
node-version: 18
|
||||||
- run: yarn install --frozen-lockfile --check-files
|
- run: yarn install --frozen-lockfile --check-files
|
||||||
- run: sudo apt-get install nsis
|
- run: sudo apt-get install nsis
|
||||||
- run: yarn build
|
- run: yarn build
|
||||||
@@ -138,7 +138,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
registry-url: 'https://registry.npmjs.org/'
|
registry-url: 'https://registry.npmjs.org/'
|
||||||
scope: 'expo'
|
scope: 'expo'
|
||||||
node-version: '16'
|
node-version: 18
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: yarn install --frozen-lockfile --check-files
|
run: yarn install --frozen-lockfile --check-files
|
||||||
- name: Build
|
- name: Build
|
||||||
@@ -155,7 +155,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: '16'
|
node-version: 18
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
working-directory: ./scripts
|
working-directory: ./scripts
|
||||||
run: yarn install --frozen-lockfile --check-files
|
run: yarn install --frozen-lockfile --check-files
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
- uses: preactjs/compressed-size-action@v2
|
- uses: preactjs/compressed-size-action@v2
|
||||||
with:
|
with:
|
||||||
build-script: 'build:tarballs:linux'
|
build-script: 'build:tarballs:linux'
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -10,9 +10,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node: ['12', '14', '16']
|
node: ['14', '16', '18']
|
||||||
include:
|
include:
|
||||||
- node: '16'
|
- node: '18'
|
||||||
coverage: true
|
coverage: true
|
||||||
name: Test with Node ${{ matrix.node }}
|
name: Test with Node ${{ matrix.node }}
|
||||||
steps:
|
steps:
|
||||||
@@ -27,6 +27,10 @@ jobs:
|
|||||||
if: ${{ !matrix.coverage }}
|
if: ${{ !matrix.coverage }}
|
||||||
- run: yarn test --coverage
|
- run: yarn test --coverage
|
||||||
if: ${{ matrix.coverage }}
|
if: ${{ matrix.coverage }}
|
||||||
|
env:
|
||||||
|
# Oclif seems to cause OOM errors when testing with coverage enabled.
|
||||||
|
# Remove this whenever we solved those OOM errors.
|
||||||
|
NODE_OPTIONS: --max-old-space-size=4096
|
||||||
- run: yarn lint --max-warnings=0
|
- run: yarn lint --max-warnings=0
|
||||||
- run: shellcheck bin/*.sh
|
- run: shellcheck bin/*.sh
|
||||||
- uses: codecov/codecov-action@v1
|
- uses: codecov/codecov-action@v1
|
||||||
|
|||||||
@@ -2,10 +2,12 @@
|
|||||||
packages/*/build
|
packages/*/build
|
||||||
packages/eas-cli/dist
|
packages/eas-cli/dist
|
||||||
packages/eas-cli/tmp
|
packages/eas-cli/tmp
|
||||||
|
scripts/build
|
||||||
|
|
||||||
# Code editors
|
# Code editors
|
||||||
.idea
|
.idea
|
||||||
.history
|
.history
|
||||||
|
.vscode
|
||||||
|
|
||||||
# macOS
|
# macOS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|||||||
+109
@@ -8,10 +8,119 @@ This is the log of notable changes to EAS CLI and related packages.
|
|||||||
|
|
||||||
### 🎉 New features
|
### 🎉 New features
|
||||||
|
|
||||||
|
- Add support for attaching messages to builds. ([#1237](https://github.com/expo/eas-cli/pull/1237) by [@dsokal](https://github.com/dsokal))
|
||||||
|
|
||||||
### 🐛 Bug fixes
|
### 🐛 Bug fixes
|
||||||
|
|
||||||
### 🧹 Chores
|
### 🧹 Chores
|
||||||
|
|
||||||
|
## [0.56.0](https://github.com/expo/eas-cli/releases/tag/v0.56.0) - 2022-07-28
|
||||||
|
|
||||||
|
### 🎉 New features
|
||||||
|
|
||||||
|
- Display build queue type when waiting. ([#1217](https://github.com/expo/eas-cli/pull/1217) by [@dsokal](https://github.com/dsokal))
|
||||||
|
- Add better message on how to upgrade EAS CLI. ([#1222](https://github.com/expo/eas-cli/pull/1222) by [@jeremybarbet](https://github.com/jeremybarbet), [#1231](https://github.com/expo/eas-cli/pull/1231) by [@wkozyra95](https://github.com/wkozyra95))
|
||||||
|
- Invoke export with sourcemaps on update. ([#1228](https://github.com/expo/eas-cli/pull/1228) by [@kbrandwijk](https://github.com/kbrandwijk))
|
||||||
|
- Add new option to `eas device:create` - allow importing devices from Apple Developer Portal. ([#1236](https://github.com/expo/eas-cli/pull/1236) by [@dsokal](https://github.com/dsokal))
|
||||||
|
|
||||||
|
### 🐛 Bug fixes
|
||||||
|
|
||||||
|
- Show spinner instead of silently timing out during asset upload. ([#1206](https://github.com/expo/eas-cli/pull/1206) by [@wschurman](https://github.com/wschurman))
|
||||||
|
- Fix build archive S3 URLs. ([#1207](https://github.com/expo/eas-cli/pull/1207) by [@dsokal](https://github.com/dsokal))
|
||||||
|
- `autoIncrement` option on iOS will update versions of all targets that depend on an application target. ([#1219](https://github.com/expo/eas-cli/pull/1219) by [@wkozyra95](https://github.com/wkozyra95))
|
||||||
|
|
||||||
|
### 🧹 Chores
|
||||||
|
|
||||||
|
- Increase max number of chained "extends" in build profiles. ([#1208](https://github.com/expo/eas-cli/pull/1208) by [@wkozyra95](https://github.com/wkozyra95))
|
||||||
|
- Change wording on build warning for bundle id/package name. ([#1211](https://github.com/expo/eas-cli/pull/1211) by [@kbrandwijk](https://github.com/kbrandwijk))
|
||||||
|
|
||||||
|
## [0.55.1](https://github.com/expo/eas-cli/releases/tag/v0.55.1) - 2022-07-12
|
||||||
|
|
||||||
|
### 🐛 Bug fixes
|
||||||
|
|
||||||
|
- Fix asset upload crash. ([#1205](https://github.com/expo/eas-cli/pull/1205) by [@wschurman](https://github.com/wschurman))
|
||||||
|
|
||||||
|
## [0.55.0](https://github.com/expo/eas-cli/releases/tag/v0.55.0) - 2022-07-11
|
||||||
|
|
||||||
|
### 🎉 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))
|
||||||
|
- Override applicationId via env. ([#1203](https://github.com/expo/eas-cli/pull/1203) by [@wkozyra95](https://github.com/wkozyra95))
|
||||||
|
|
||||||
|
### 🐛 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
|
## [0.52.0](https://github.com/expo/eas-cli/releases/tag/v0.52.0) - 2022-04-26
|
||||||
|
|
||||||
### 🎉 New features
|
### 🎉 New features
|
||||||
|
|||||||
@@ -1,7 +1,16 @@
|
|||||||
|
* @dsokal @wkozyra95
|
||||||
|
|
||||||
packages/eas-cli/src/build @dsokal @wkozyra95
|
packages/eas-cli/src/build @dsokal @wkozyra95
|
||||||
packages/eas-cli/src/commands/build @dsokal @wkozyra95
|
packages/eas-cli/src/commands/build @dsokal @wkozyra95
|
||||||
|
|
||||||
packages/eas-cli/src/submit @barthap @dsokal
|
packages/eas-cli/src/submit @barthap @dsokal
|
||||||
packages/eas-cli/src/commands/submit.ts @barthap @dsokal
|
packages/eas-cli/src/commands/submit.ts @barthap @dsokal
|
||||||
|
|
||||||
|
packages/eas-cli/src/update @kgc00 @wschurman
|
||||||
|
packages/eas-cli/src/commands/update @kgc00 @wschurman
|
||||||
|
|
||||||
|
packages/eas-cli/schema @bycedric
|
||||||
|
packages/eas-cli/src/metadata @bycedric
|
||||||
|
packages/eas-cli/src/commands/metadata @bycedric
|
||||||
|
|
||||||
packages/eas-json @dsokal @wkozyra95
|
packages/eas-json @dsokal @wkozyra95
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"useWorkspaces": true,
|
"useWorkspaces": true,
|
||||||
"version": "0.52.0"
|
"version": "0.56.0"
|
||||||
}
|
}
|
||||||
+12
-12
@@ -17,22 +17,22 @@
|
|||||||
"clean": "lerna run clean && rm -rf node_modules coverage"
|
"clean": "lerna run clean && rm -rf node_modules coverage"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "27.4.1",
|
"@types/jest": "27.5.0",
|
||||||
"@types/node": "16.7.8",
|
"@types/node": "17.0.32",
|
||||||
"eslint": "8.12.0",
|
"eslint": "8.15.0",
|
||||||
"eslint-config-universe": "10.0.0",
|
"eslint-config-universe": "11.0.0",
|
||||||
"eslint-plugin-async-protect": "1.1.0",
|
"eslint-plugin-async-protect": "1.1.0",
|
||||||
"eslint-plugin-node": "11.1.0",
|
"eslint-plugin-node": "11.1.0",
|
||||||
"jest": "27.5.1",
|
"jest": "28.1.0",
|
||||||
"jest-watch-typeahead": "1.0.0",
|
"jest-watch-typeahead": "1.1.0",
|
||||||
"lerna": "4.0.0",
|
"lerna": "4.0.0",
|
||||||
"oclif": "2.6.3",
|
"oclif": "3.0.1",
|
||||||
"prettier": "2.6.1",
|
"prettier": "2.6.2",
|
||||||
"ts-jest": "27.1.4",
|
"ts-jest": "28.0.2",
|
||||||
"typescript": "4.6.3"
|
"typescript": "4.7.4"
|
||||||
},
|
},
|
||||||
"volta": {
|
"volta": {
|
||||||
"node": "16.10.0",
|
"node": "18.6.0",
|
||||||
"yarn": "1.22.15"
|
"yarn": "1.22.19"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+80
-44
@@ -65,6 +65,8 @@ eas --help COMMAND
|
|||||||
* [`eas init`](#eas-init)
|
* [`eas init`](#eas-init)
|
||||||
* [`eas login`](#eas-login)
|
* [`eas login`](#eas-login)
|
||||||
* [`eas logout`](#eas-logout)
|
* [`eas logout`](#eas-logout)
|
||||||
|
* [`eas metadata:pull`](#eas-metadatapull)
|
||||||
|
* [`eas metadata:push`](#eas-metadatapush)
|
||||||
* [`eas project:info`](#eas-projectinfo)
|
* [`eas project:info`](#eas-projectinfo)
|
||||||
* [`eas project:init`](#eas-projectinit)
|
* [`eas project:init`](#eas-projectinit)
|
||||||
* [`eas secret:create`](#eas-secretcreate)
|
* [`eas secret:create`](#eas-secretcreate)
|
||||||
@@ -98,7 +100,7 @@ ALIASES
|
|||||||
$ eas login
|
$ eas login
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/account/login.ts)_
|
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/account/login.ts)_
|
||||||
|
|
||||||
## `eas account:logout`
|
## `eas account:logout`
|
||||||
|
|
||||||
@@ -115,7 +117,7 @@ ALIASES
|
|||||||
$ eas logout
|
$ eas logout
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/account/logout.ts)_
|
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/account/logout.ts)_
|
||||||
|
|
||||||
## `eas account:view`
|
## `eas account:view`
|
||||||
|
|
||||||
@@ -132,7 +134,7 @@ ALIASES
|
|||||||
$ eas whoami
|
$ eas whoami
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/account/view.ts)_
|
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/account/view.ts)_
|
||||||
|
|
||||||
## `eas analytics [STATUS]`
|
## `eas analytics [STATUS]`
|
||||||
|
|
||||||
@@ -146,7 +148,7 @@ DESCRIPTION
|
|||||||
display or change analytics settings
|
display or change analytics settings
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/analytics.ts)_
|
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/analytics.ts)_
|
||||||
|
|
||||||
## `eas autocomplete [SHELL]`
|
## `eas autocomplete [SHELL]`
|
||||||
|
|
||||||
@@ -175,7 +177,7 @@ EXAMPLES
|
|||||||
$ eas autocomplete --refresh-cache
|
$ 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]`
|
## `eas branch:create [NAME]`
|
||||||
|
|
||||||
@@ -195,7 +197,7 @@ DESCRIPTION
|
|||||||
create a branch
|
create a branch
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/branch/create.ts)_
|
_See code: [src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/branch/create.ts)_
|
||||||
|
|
||||||
## `eas branch:delete [NAME]`
|
## `eas branch:delete [NAME]`
|
||||||
|
|
||||||
@@ -215,7 +217,7 @@ DESCRIPTION
|
|||||||
delete a branch
|
delete a branch
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/branch/delete.ts)_
|
_See code: [src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/branch/delete.ts)_
|
||||||
|
|
||||||
## `eas branch:list`
|
## `eas branch:list`
|
||||||
|
|
||||||
@@ -232,7 +234,7 @@ DESCRIPTION
|
|||||||
list all branches
|
list all branches
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/branch/list.ts)_
|
_See code: [src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/branch/list.ts)_
|
||||||
|
|
||||||
## `eas branch:rename`
|
## `eas branch:rename`
|
||||||
|
|
||||||
@@ -251,7 +253,7 @@ DESCRIPTION
|
|||||||
rename a branch
|
rename a branch
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/branch/rename.ts)_
|
_See code: [src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/branch/rename.ts)_
|
||||||
|
|
||||||
## `eas branch:view [NAME]`
|
## `eas branch:view [NAME]`
|
||||||
|
|
||||||
@@ -271,7 +273,7 @@ DESCRIPTION
|
|||||||
view a branch
|
view a branch
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/branch/view.ts)_
|
_See code: [src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/branch/view.ts)_
|
||||||
|
|
||||||
## `eas build`
|
## `eas build`
|
||||||
|
|
||||||
@@ -300,7 +302,7 @@ DESCRIPTION
|
|||||||
start a build
|
start a build
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/build/index.ts)_
|
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/build/index.ts)_
|
||||||
|
|
||||||
## `eas build:cancel [BUILD_ID]`
|
## `eas build:cancel [BUILD_ID]`
|
||||||
|
|
||||||
@@ -314,7 +316,7 @@ DESCRIPTION
|
|||||||
cancel a build
|
cancel a build
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/build/cancel.ts)_
|
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/build/cancel.ts)_
|
||||||
|
|
||||||
## `eas build:configure`
|
## `eas build:configure`
|
||||||
|
|
||||||
@@ -331,7 +333,7 @@ DESCRIPTION
|
|||||||
configure the project to support EAS Build
|
configure the project to support EAS Build
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/build/configure.ts)_
|
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/build/configure.ts)_
|
||||||
|
|
||||||
## `eas build:inspect`
|
## `eas build:inspect`
|
||||||
|
|
||||||
@@ -366,7 +368,7 @@ DESCRIPTION
|
|||||||
inspect the state of the project at specific build stages, useful for troubleshooting
|
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.52.0/packages/eas-cli/src/commands/build/inspect.ts)_
|
_See code: [src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/build/inspect.ts)_
|
||||||
|
|
||||||
## `eas build:list`
|
## `eas build:list`
|
||||||
|
|
||||||
@@ -399,7 +401,7 @@ DESCRIPTION
|
|||||||
list all builds for your project
|
list all builds for your project
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/build/list.ts)_
|
_See code: [src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/build/list.ts)_
|
||||||
|
|
||||||
## `eas build:submit`
|
## `eas build:submit`
|
||||||
|
|
||||||
@@ -444,7 +446,7 @@ DESCRIPTION
|
|||||||
view a build for your project
|
view a build for your project
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/build/view.ts)_
|
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/build/view.ts)_
|
||||||
|
|
||||||
## `eas channel:create [NAME]`
|
## `eas channel:create [NAME]`
|
||||||
|
|
||||||
@@ -464,7 +466,7 @@ DESCRIPTION
|
|||||||
create a channel
|
create a channel
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/channel/create.ts)_
|
_See code: [src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/channel/create.ts)_
|
||||||
|
|
||||||
## `eas channel:edit [NAME]`
|
## `eas channel:edit [NAME]`
|
||||||
|
|
||||||
@@ -485,7 +487,7 @@ DESCRIPTION
|
|||||||
point a channel at a new branch
|
point a channel at a new branch
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/channel/edit.ts)_
|
_See code: [src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/channel/edit.ts)_
|
||||||
|
|
||||||
## `eas channel:list`
|
## `eas channel:list`
|
||||||
|
|
||||||
@@ -502,7 +504,7 @@ DESCRIPTION
|
|||||||
list all channels
|
list all channels
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/channel/list.ts)_
|
_See code: [src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/channel/list.ts)_
|
||||||
|
|
||||||
## `eas channel:view [NAME]`
|
## `eas channel:view [NAME]`
|
||||||
|
|
||||||
@@ -522,7 +524,7 @@ DESCRIPTION
|
|||||||
view a channel
|
view a channel
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/channel/view.ts)_
|
_See code: [src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/channel/view.ts)_
|
||||||
|
|
||||||
## `eas config`
|
## `eas config`
|
||||||
|
|
||||||
@@ -540,7 +542,7 @@ DESCRIPTION
|
|||||||
display project configuration (app.json + eas.json)
|
display project configuration (app.json + eas.json)
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/config.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/config.ts)_
|
_See code: [src/commands/config.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/config.ts)_
|
||||||
|
|
||||||
## `eas credentials`
|
## `eas credentials`
|
||||||
|
|
||||||
@@ -554,7 +556,7 @@ DESCRIPTION
|
|||||||
manage credentials
|
manage credentials
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/credentials.ts)_
|
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/credentials.ts)_
|
||||||
|
|
||||||
## `eas device:create`
|
## `eas device:create`
|
||||||
|
|
||||||
@@ -568,7 +570,7 @@ DESCRIPTION
|
|||||||
register new Apple Devices to use for internal distribution
|
register new Apple Devices to use for internal distribution
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/device/create.ts)_
|
_See code: [src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/device/create.ts)_
|
||||||
|
|
||||||
## `eas device:delete`
|
## `eas device:delete`
|
||||||
|
|
||||||
@@ -586,7 +588,7 @@ DESCRIPTION
|
|||||||
remove a registered device from your account
|
remove a registered device from your account
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/device/delete.ts)_
|
_See code: [src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/device/delete.ts)_
|
||||||
|
|
||||||
## `eas device:list`
|
## `eas device:list`
|
||||||
|
|
||||||
@@ -603,7 +605,7 @@ DESCRIPTION
|
|||||||
list all registered devices for your account
|
list all registered devices for your account
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/device/list.ts)_
|
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/device/list.ts)_
|
||||||
|
|
||||||
## `eas device:view [UDID]`
|
## `eas device:view [UDID]`
|
||||||
|
|
||||||
@@ -617,7 +619,7 @@ DESCRIPTION
|
|||||||
view a device for your project
|
view a device for your project
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/device/view.ts)_
|
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/device/view.ts)_
|
||||||
|
|
||||||
## `eas diagnostics`
|
## `eas diagnostics`
|
||||||
|
|
||||||
@@ -631,7 +633,7 @@ DESCRIPTION
|
|||||||
display environment info
|
display environment info
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/diagnostics.ts)_
|
_See code: [src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/diagnostics.ts)_
|
||||||
|
|
||||||
## `eas help [COMMAND]`
|
## `eas help [COMMAND]`
|
||||||
|
|
||||||
@@ -651,7 +653,7 @@ DESCRIPTION
|
|||||||
Display help for eas.
|
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`
|
## `eas init`
|
||||||
|
|
||||||
@@ -698,6 +700,40 @@ ALIASES
|
|||||||
$ eas logout
|
$ 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.56.0/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.56.0/packages/eas-cli/src/commands/metadata/push.ts)_
|
||||||
|
|
||||||
## `eas project:info`
|
## `eas project:info`
|
||||||
|
|
||||||
information about the current project
|
information about the current project
|
||||||
@@ -710,7 +746,7 @@ DESCRIPTION
|
|||||||
information about the current project
|
information about the current project
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/project/info.ts)_
|
_See code: [src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/project/info.ts)_
|
||||||
|
|
||||||
## `eas project:init`
|
## `eas project:init`
|
||||||
|
|
||||||
@@ -727,7 +763,7 @@ ALIASES
|
|||||||
$ eas init
|
$ eas init
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/project/init.ts)_
|
_See code: [src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/project/init.ts)_
|
||||||
|
|
||||||
## `eas secret:create`
|
## `eas secret:create`
|
||||||
|
|
||||||
@@ -747,7 +783,7 @@ DESCRIPTION
|
|||||||
create an environment secret on the current project or owner account
|
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.52.0/packages/eas-cli/src/commands/secret/create.ts)_
|
_See code: [src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/secret/create.ts)_
|
||||||
|
|
||||||
## `eas secret:delete`
|
## `eas secret:delete`
|
||||||
|
|
||||||
@@ -764,7 +800,7 @@ DESCRIPTION
|
|||||||
delete an environment secret by ID
|
delete an environment secret by ID
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/secret/delete.ts)_
|
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/secret/delete.ts)_
|
||||||
|
|
||||||
## `eas secret:list`
|
## `eas secret:list`
|
||||||
|
|
||||||
@@ -778,7 +814,7 @@ DESCRIPTION
|
|||||||
list environment secrets available for your current app
|
list environment secrets available for your current app
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/secret/list.ts)_
|
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/secret/list.ts)_
|
||||||
|
|
||||||
## `eas submit`
|
## `eas submit`
|
||||||
|
|
||||||
@@ -808,7 +844,7 @@ ALIASES
|
|||||||
$ eas build:submit
|
$ eas build:submit
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/submit.ts)_
|
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/submit.ts)_
|
||||||
|
|
||||||
## `eas update`
|
## `eas update`
|
||||||
|
|
||||||
@@ -838,7 +874,7 @@ DESCRIPTION
|
|||||||
publish an update group
|
publish an update group
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/update/index.ts)_
|
_See code: [src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/update/index.ts)_
|
||||||
|
|
||||||
## `eas update:configure`
|
## `eas update:configure`
|
||||||
|
|
||||||
@@ -855,7 +891,7 @@ DESCRIPTION
|
|||||||
configure the project to support EAS Update
|
configure the project to support EAS Update
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/update/configure.ts)_
|
_See code: [src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/update/configure.ts)_
|
||||||
|
|
||||||
## `eas update:delete GROUPID`
|
## `eas update:delete GROUPID`
|
||||||
|
|
||||||
@@ -875,7 +911,7 @@ DESCRIPTION
|
|||||||
delete all the updates in an update group
|
delete all the updates in an update group
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/update/delete.ts)_
|
_See code: [src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/update/delete.ts)_
|
||||||
|
|
||||||
## `eas update:list`
|
## `eas update:list`
|
||||||
|
|
||||||
@@ -894,7 +930,7 @@ DESCRIPTION
|
|||||||
view the recent updates for a branch
|
view the recent updates for a branch
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/update/list.ts)_
|
_See code: [src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/update/list.ts)_
|
||||||
|
|
||||||
## `eas update:view GROUPID`
|
## `eas update:view GROUPID`
|
||||||
|
|
||||||
@@ -914,7 +950,7 @@ DESCRIPTION
|
|||||||
update group details
|
update group details
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/update/view.ts)_
|
_See code: [src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/update/view.ts)_
|
||||||
|
|
||||||
## `eas webhook:create`
|
## `eas webhook:create`
|
||||||
|
|
||||||
@@ -934,7 +970,7 @@ DESCRIPTION
|
|||||||
create a webhook
|
create a webhook
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/webhook/create.ts)_
|
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/webhook/create.ts)_
|
||||||
|
|
||||||
## `eas webhook:delete [ID]`
|
## `eas webhook:delete [ID]`
|
||||||
|
|
||||||
@@ -951,7 +987,7 @@ DESCRIPTION
|
|||||||
delete a webhook
|
delete a webhook
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/webhook/delete.ts)_
|
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/webhook/delete.ts)_
|
||||||
|
|
||||||
## `eas webhook:list`
|
## `eas webhook:list`
|
||||||
|
|
||||||
@@ -968,7 +1004,7 @@ DESCRIPTION
|
|||||||
list webhooks
|
list webhooks
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/webhook/list.ts)_
|
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/webhook/list.ts)_
|
||||||
|
|
||||||
## `eas webhook:update`
|
## `eas webhook:update`
|
||||||
|
|
||||||
@@ -989,7 +1025,7 @@ DESCRIPTION
|
|||||||
update a webhook
|
update a webhook
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/webhook/update.ts)_
|
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/webhook/update.ts)_
|
||||||
|
|
||||||
## `eas webhook:view ID`
|
## `eas webhook:view ID`
|
||||||
|
|
||||||
@@ -1006,7 +1042,7 @@ DESCRIPTION
|
|||||||
view a webhook
|
view a webhook
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v0.52.0/packages/eas-cli/src/commands/webhook/view.ts)_
|
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v0.56.0/packages/eas-cli/src/commands/webhook/view.ts)_
|
||||||
|
|
||||||
## `eas whoami`
|
## `eas whoami`
|
||||||
|
|
||||||
|
|||||||
Generated
+2238
-96
File diff suppressed because it is too large.
Load diff
@@ -1,38 +1,39 @@
|
|||||||
{
|
{
|
||||||
"name": "eas-cli",
|
"name": "eas-cli",
|
||||||
"description": "EAS command line tool",
|
"description": "EAS command line tool",
|
||||||
"version": "0.52.0",
|
"version": "0.56.0",
|
||||||
"author": "Expo <[email protected]>",
|
"author": "Expo <[email protected]>",
|
||||||
"bin": {
|
"bin": {
|
||||||
"eas": "./bin/run"
|
"eas": "./bin/run"
|
||||||
},
|
},
|
||||||
"bugs": "https://github.com/expo/eas-cli/issues",
|
"bugs": "https://github.com/expo/eas-cli/issues",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@expo/apple-utils": "0.0.0-alpha.31",
|
"@expo/apple-utils": "0.0.0-alpha.33",
|
||||||
"@expo/code-signing-certificates": "0.0.2",
|
"@expo/code-signing-certificates": "0.0.2",
|
||||||
"@expo/config": "6.0.21",
|
"@expo/config": "6.0.23",
|
||||||
"@expo/config-plugins": "4.1.2",
|
"@expo/config-plugins": "4.1.4",
|
||||||
"@expo/config-types": "44.0.0",
|
"@expo/config-types": "45.0.0",
|
||||||
"@expo/eas-build-job": "0.2.71",
|
"@expo/eas-build-job": "0.2.82",
|
||||||
"@expo/eas-json": "0.52.0",
|
"@expo/eas-json": "0.56.0",
|
||||||
"@expo/json-file": "8.2.34",
|
"@expo/json-file": "8.2.36",
|
||||||
"@expo/multipart-body-parser": "1.1.0",
|
"@expo/multipart-body-parser": "1.1.0",
|
||||||
"@expo/pkcs12": "0.0.7",
|
"@expo/pkcs12": "0.0.8",
|
||||||
"@expo/plist": "0.0.17",
|
"@expo/plist": "0.0.18",
|
||||||
"@expo/plugin-warn-if-update-available": "2.1.0",
|
"@expo/plugin-autocomplete": "1.4.0",
|
||||||
"@expo/prebuild-config": "3.1.2",
|
"@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/results": "1.0.0",
|
||||||
"@expo/rudder-sdk-node": "1.1.1",
|
"@expo/rudder-sdk-node": "1.1.1",
|
||||||
"@expo/spawn-async": "1.6.0",
|
"@expo/spawn-async": "1.6.0",
|
||||||
"@expo/timeago.js": "1.0.0",
|
"@expo/timeago.js": "1.0.0",
|
||||||
"@oclif/core": "1.6.4",
|
"@oclif/core": "1.9.0",
|
||||||
"@oclif/plugin-autocomplete": "1.2.0",
|
"@urql/core": "2.4.4",
|
||||||
"@oclif/plugin-help": "5.1.12",
|
"@urql/exchange-retry": "0.3.3",
|
||||||
"@urql/core": "2.4.3",
|
"ajv": "^6.12.6",
|
||||||
"@urql/exchange-retry": "0.3.2",
|
|
||||||
"chalk": "4.1.2",
|
"chalk": "4.1.2",
|
||||||
"cli-progress": "3.10.0",
|
"cli-progress": "3.11.0",
|
||||||
"cli-table3": "0.6.1",
|
"cli-table3": "0.6.2",
|
||||||
"dateformat": "4.6.3",
|
"dateformat": "4.6.3",
|
||||||
"env-paths": "2.2.0",
|
"env-paths": "2.2.0",
|
||||||
"envinfo": "7.8.1",
|
"envinfo": "7.8.1",
|
||||||
@@ -40,12 +41,12 @@
|
|||||||
"fast-glob": "3.2.11",
|
"fast-glob": "3.2.11",
|
||||||
"figures": "3.2.0",
|
"figures": "3.2.0",
|
||||||
"form-data": "4.0.0",
|
"form-data": "4.0.0",
|
||||||
"fs-extra": "10.0.1",
|
"fs-extra": "10.1.0",
|
||||||
"getenv": "1.0.0",
|
"getenv": "1.0.0",
|
||||||
"gradle-to-js": "2.0.0",
|
"gradle-to-js": "2.0.1",
|
||||||
"graphql": "16.3.0",
|
"graphql": "16.5.0",
|
||||||
"graphql-tag": "2.12.6",
|
"graphql-tag": "2.12.6",
|
||||||
"https-proxy-agent": "5.0.0",
|
"https-proxy-agent": "5.0.1",
|
||||||
"ignore": "5.2.0",
|
"ignore": "5.2.0",
|
||||||
"indent-string": "4.0.0",
|
"indent-string": "4.0.0",
|
||||||
"jks-js": "1.0.2",
|
"jks-js": "1.0.2",
|
||||||
@@ -53,22 +54,23 @@
|
|||||||
"keychain": "1.3.0",
|
"keychain": "1.3.0",
|
||||||
"log-symbols": "4.1.0",
|
"log-symbols": "4.1.0",
|
||||||
"mime": "3.0.0",
|
"mime": "3.0.0",
|
||||||
"minimatch": "3.0.5",
|
"minimatch": "5.0.1",
|
||||||
"nanoid": "3.3.2",
|
"nanoid": "3.3.4",
|
||||||
"node-fetch": "2.6.7",
|
"node-fetch": "2.6.7",
|
||||||
"node-forge": "1.3.1",
|
"node-forge": "1.3.1",
|
||||||
"nullthrows": "1.1.1",
|
"nullthrows": "1.1.1",
|
||||||
"ora": "5.1.0",
|
"ora": "5.1.0",
|
||||||
"pkg-dir": "4.2.0",
|
"pkg-dir": "4.2.0",
|
||||||
|
"promise-limit": "2.7.0",
|
||||||
"prompts": "2.4.2",
|
"prompts": "2.4.2",
|
||||||
"qrcode-terminal": "0.12.0",
|
"qrcode-terminal": "0.12.0",
|
||||||
"resolve-from": "5.0.0",
|
"resolve-from": "5.0.0",
|
||||||
"semver": "7.3.5",
|
"semver": "7.3.7",
|
||||||
"slash": "3.0.0",
|
"slash": "3.0.0",
|
||||||
"strip-ansi": "6.0.0",
|
"strip-ansi": "6.0.0",
|
||||||
"tar": "6.1.11",
|
"tar": "6.1.11",
|
||||||
"terminal-link": "2.1.1",
|
"terminal-link": "2.1.1",
|
||||||
"tslib": "2.3.1",
|
"tslib": "2.4.0",
|
||||||
"turndown": "7.1.1",
|
"turndown": "7.1.1",
|
||||||
"untildify": "4.0.0",
|
"untildify": "4.0.0",
|
||||||
"uuid": "8.3.2",
|
"uuid": "8.3.2",
|
||||||
@@ -77,8 +79,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@graphql-codegen/cli": "2.6.2",
|
"@graphql-codegen/cli": "2.6.2",
|
||||||
"@graphql-codegen/introspection": "2.1.1",
|
"@graphql-codegen/introspection": "2.1.1",
|
||||||
"@graphql-codegen/typescript": "2.4.8",
|
"@graphql-codegen/typescript": "2.4.11",
|
||||||
"@graphql-codegen/typescript-operations": "2.3.5",
|
"@graphql-codegen/typescript-operations": "2.4.0",
|
||||||
"@types/cli-progress": "3.9.2",
|
"@types/cli-progress": "3.9.2",
|
||||||
"@types/dateformat": "3.0.1",
|
"@types/dateformat": "3.0.1",
|
||||||
"@types/envinfo": "7.8.1",
|
"@types/envinfo": "7.8.1",
|
||||||
@@ -86,30 +88,32 @@
|
|||||||
"@types/getenv": "^1.0.0",
|
"@types/getenv": "^1.0.0",
|
||||||
"@types/mime": "2.0.3",
|
"@types/mime": "2.0.3",
|
||||||
"@types/node-fetch": "^2.5.7",
|
"@types/node-fetch": "^2.5.7",
|
||||||
"@types/node-forge": "1.0.1",
|
"@types/node-forge": "1.0.2",
|
||||||
"@types/prompts": "2.0.14",
|
"@types/prompts": "2.0.14",
|
||||||
"@types/semver": "7.3.9",
|
"@types/semver": "7.3.9",
|
||||||
"@types/tar": "6.1.1",
|
"@types/tar": "6.1.1",
|
||||||
"@types/tough-cookie": "4.0.1",
|
"@types/tough-cookie": "4.0.2",
|
||||||
"@types/uuid": "8.3.4",
|
"@types/uuid": "8.3.4",
|
||||||
"@types/wrap-ansi": "3.0.0",
|
"@types/wrap-ansi": "3.0.0",
|
||||||
"axios": "0.26.1",
|
"axios": "0.27.2",
|
||||||
"eslint-plugin-graphql": "4.0.0",
|
"eslint-plugin-graphql": "4.0.0",
|
||||||
"form-data": "4.0.0",
|
"form-data": "4.0.0",
|
||||||
"memfs": "3.4.1",
|
"memfs": "3.4.3",
|
||||||
"mockdate": "3.0.5",
|
"mockdate": "3.0.5",
|
||||||
"nock": "13.2.4",
|
"nock": "13.2.4",
|
||||||
"tempy": "0.7.0",
|
"tempy": "0.7.0",
|
||||||
"ts-deepmerge": "2.0.1",
|
"ts-deepmerge": "2.0.1",
|
||||||
"typescript": "4.6.3"
|
"ts-mockito": "2.6.1",
|
||||||
|
"typescript": "4.7.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12.0.0"
|
"node": ">=14.0.0"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"/bin",
|
"/bin",
|
||||||
"/build",
|
"/build",
|
||||||
"/oclif.manifest.json"
|
"/oclif.manifest.json",
|
||||||
|
"/schema"
|
||||||
],
|
],
|
||||||
"homepage": "https://github.com/expo/eas-cli",
|
"homepage": "https://github.com/expo/eas-cli",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@@ -122,8 +126,8 @@
|
|||||||
"bin": "eas",
|
"bin": "eas",
|
||||||
"commands": "./build/commands",
|
"commands": "./build/commands",
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"@oclif/plugin-autocomplete",
|
"@expo/plugin-autocomplete",
|
||||||
"@oclif/plugin-help",
|
"@expo/plugin-help",
|
||||||
"@expo/plugin-warn-if-update-available"
|
"@expo/plugin-warn-if-update-available"
|
||||||
],
|
],
|
||||||
"topics": {
|
"topics": {
|
||||||
@@ -142,6 +146,9 @@
|
|||||||
"device": {
|
"device": {
|
||||||
"description": "manage Apple devices for Internal Distribution"
|
"description": "manage Apple devices for Internal Distribution"
|
||||||
},
|
},
|
||||||
|
"metadata": {
|
||||||
|
"description": "manage store configuration"
|
||||||
|
},
|
||||||
"project": {
|
"project": {
|
||||||
"description": "manage project"
|
"description": "manage project"
|
||||||
},
|
},
|
||||||
@@ -160,7 +167,7 @@
|
|||||||
},
|
},
|
||||||
"warn-if-update-available": {
|
"warn-if-update-available": {
|
||||||
"timeoutInDays": 0.5,
|
"timeoutInDays": 0.5,
|
||||||
"message": "<%= chalk.bold('★') %> <%= chalk.bold(config.name + '@' + latest) %> <%= chalk.bold('is now available, please upgrade.') %>\n<%= chalk.dim('Proceeding with outdated version') %>\n"
|
"message": "<%= chalk('★') %> <%= chalk.bold(config.name + '@' + latest) %> <%= chalk.bold('is now available.') %>\n<%= chalk.dim('To upgrade, run ') %><%= chalk.dim(chalk.bold('npm install -g eas-cli')) %><%= chalk.dim('.') %>\n<%= chalk.dim('Proceeding with outdated version.') %>\n"
|
||||||
},
|
},
|
||||||
"update": {
|
"update": {
|
||||||
"node": {
|
"node": {
|
||||||
@@ -194,5 +201,9 @@
|
|||||||
"version": "yarn oclif readme && node scripts/patch-readme && git add README.md",
|
"version": "yarn oclif readme && node scripts/patch-readme && git add README.md",
|
||||||
"generate-graphql-code": "graphql-codegen --config graphql-codegen.yml",
|
"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"
|
||||||
|
},
|
||||||
|
"volta": {
|
||||||
|
"node": "18.6.0",
|
||||||
|
"yarn": "1.22.19"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { fixS3Url } from '../uploads';
|
||||||
|
|
||||||
|
describe(fixS3Url, () => {
|
||||||
|
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(fixS3Url(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(fixS3Url(correctUrl)).toBe(correctUrl);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { logEvent } from './rudderstackClient';
|
import { logEvent } from './rudderstackClient';
|
||||||
export type Event = BuildEvent | SubmissionEvent;
|
export type Event = BuildEvent | SubmissionEvent | MetadataEvent;
|
||||||
|
|
||||||
export enum SubmissionEvent {
|
export enum SubmissionEvent {
|
||||||
SUBMIT_COMMAND = 'submit cli submit command',
|
SUBMIT_COMMAND = 'submit cli submit command',
|
||||||
@@ -45,6 +45,11 @@ export enum BuildEvent {
|
|||||||
ANDROID_KEYSTORE_CREATE = 'build cli credentials keystore create',
|
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 {
|
export class Analytics {
|
||||||
static logEvent(name: Event, properties: Record<string, any>): void {
|
static logEvent(name: Event, properties: Record<string, any>): void {
|
||||||
logEvent(name, properties);
|
logEvent(name, properties);
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { instance, mock, when } from 'ts-mockito';
|
||||||
|
|
||||||
|
import { Client } from '../../vcs/vcs';
|
||||||
|
import { getFormattedCommitMessageAsync } from '../metadata';
|
||||||
|
|
||||||
|
describe(getFormattedCommitMessageAsync, () => {
|
||||||
|
it(`returns undefined if it's not a git project`, async () => {
|
||||||
|
const clientMock = mock<Client>();
|
||||||
|
when(clientMock.getLastCommitMessageAsync()).thenResolve(null);
|
||||||
|
const client = instance(clientMock);
|
||||||
|
|
||||||
|
await expect(getFormattedCommitMessageAsync(client)).resolves.toBe(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns commit message', async () => {
|
||||||
|
const clientMock = mock<Client>();
|
||||||
|
when(clientMock.getLastCommitMessageAsync()).thenResolve('lorem ipsum');
|
||||||
|
const client = instance(clientMock);
|
||||||
|
|
||||||
|
await expect(getFormattedCommitMessageAsync(client)).resolves.toBe('lorem ipsum');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('trims long commit messages', async () => {
|
||||||
|
const clientMock = mock<Client>();
|
||||||
|
when(clientMock.getLastCommitMessageAsync()).thenResolve('a'.repeat(1500));
|
||||||
|
const client = instance(clientMock);
|
||||||
|
|
||||||
|
await expect(getFormattedCommitMessageAsync(client)).resolves.toBe(`${'a'.repeat(1021)}...`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('replaces new lines with spaces', async () => {
|
||||||
|
const clientMock = mock<Client>();
|
||||||
|
when(clientMock.getLastCommitMessageAsync()).thenResolve(`Lorem\nipsum\ndolor\nsit\namet`);
|
||||||
|
const client = instance(clientMock);
|
||||||
|
|
||||||
|
await expect(getFormattedCommitMessageAsync(client)).resolves.toBe(
|
||||||
|
`Lorem ipsum dolor sit amet`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -89,7 +89,7 @@ describe(bumpVersionAsync, () => {
|
|||||||
expect(resolveConfigValue(buildGradle, 'versionName')).toBe('3.0.0');
|
expect(resolveConfigValue(buildGradle, 'versionName')).toBe('3.0.0');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('bumps expo.version and gradle versionCode when strategy = BumpStrategy.SHORT_VERSION', async () => {
|
it('bumps expo.version and gradle versionCode when strategy = BumpStrategy.APP_VERSION', async () => {
|
||||||
const nativeVersionName = '1.0.0'; // this should be overwritten by bumpVersionAsync
|
const nativeVersionName = '1.0.0'; // this should be overwritten by bumpVersionAsync
|
||||||
const fakeExp = initBareWorkflowProject({ versionName: nativeVersionName });
|
const fakeExp = initBareWorkflowProject({ versionName: nativeVersionName });
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import nullthrows from 'nullthrows';
|
|||||||
import AndroidCredentialsProvider, {
|
import AndroidCredentialsProvider, {
|
||||||
AndroidCredentials,
|
AndroidCredentials,
|
||||||
} from '../../credentials/android/AndroidCredentialsProvider';
|
} from '../../credentials/android/AndroidCredentialsProvider';
|
||||||
|
import { BuildParamsInput } from '../../graphql/generated';
|
||||||
import { BuildMutation, BuildResult } from '../../graphql/mutations/BuildMutation';
|
import { BuildMutation, BuildResult } from '../../graphql/mutations/BuildMutation';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
import {
|
import {
|
||||||
@@ -87,7 +88,8 @@ export async function prepareAndroidBuildAsync(
|
|||||||
sendBuildRequestAsync: async (
|
sendBuildRequestAsync: async (
|
||||||
appId: string,
|
appId: string,
|
||||||
job: Android.Job,
|
job: Android.Job,
|
||||||
metadata: Metadata
|
metadata: Metadata,
|
||||||
|
buildParams: BuildParamsInput
|
||||||
): Promise<BuildResult> => {
|
): Promise<BuildResult> => {
|
||||||
const graphqlMetadata = transformMetadata(metadata);
|
const graphqlMetadata = transformMetadata(metadata);
|
||||||
const graphqlJob = transformJob(job);
|
const graphqlJob = transformJob(job);
|
||||||
@@ -95,6 +97,7 @@ export async function prepareAndroidBuildAsync(
|
|||||||
appId,
|
appId,
|
||||||
job: graphqlJob,
|
job: graphqlJob,
|
||||||
metadata: graphqlMetadata,
|
metadata: graphqlMetadata,
|
||||||
|
buildParams,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
parseGradleCommand,
|
parseGradleCommand,
|
||||||
resolveConfigValue,
|
resolveConfigValue,
|
||||||
} from '../../project/android/gradleUtils';
|
} from '../../project/android/gradleUtils';
|
||||||
|
import { getNextVersionCode } from '../../project/android/versions';
|
||||||
import { resolveWorkflowAsync } from '../../project/workflow';
|
import { resolveWorkflowAsync } from '../../project/workflow';
|
||||||
import { updateAppJsonConfigAsync } from '../utils/appJson';
|
import { updateAppJsonConfigAsync } from '../utils/appJson';
|
||||||
import { bumpAppVersionAsync, ensureStaticConfigExists } from '../utils/version';
|
import { bumpAppVersionAsync, ensureStaticConfigExists } from '../utils/version';
|
||||||
@@ -46,9 +47,10 @@ export async function bumpVersionAsync({
|
|||||||
|
|
||||||
await bumpVersionInAppJsonAsync({ bumpStrategy, projectDir, exp });
|
await bumpVersionInAppJsonAsync({ bumpStrategy, projectDir, exp });
|
||||||
Log.log('Updated versions in app.json');
|
Log.log('Updated versions in app.json');
|
||||||
await writeVersionsToBuildGradleAsync({
|
await updateNativeVersionsAsync({
|
||||||
projectDir,
|
projectDir,
|
||||||
exp,
|
version: exp.version,
|
||||||
|
versionCode: exp.android?.versionCode,
|
||||||
});
|
});
|
||||||
Log.log('Synchronized versions with build gradle');
|
Log.log('Synchronized versions with build gradle');
|
||||||
}
|
}
|
||||||
@@ -74,7 +76,7 @@ export async function bumpVersionInAppJsonAsync({
|
|||||||
await bumpAppVersionAsync({ appVersion, projectDir, exp });
|
await bumpAppVersionAsync({ appVersion, projectDir, exp });
|
||||||
} else {
|
} else {
|
||||||
const versionCode = AndroidConfig.Version.getVersionCode(exp);
|
const versionCode = AndroidConfig.Version.getVersionCode(exp);
|
||||||
const bumpedVersionCode = versionCode + 1;
|
const bumpedVersionCode = getNextVersionCode(versionCode);
|
||||||
Log.log(
|
Log.log(
|
||||||
`Bumping ${chalk.bold('expo.android.versionCode')} from ${chalk.bold(
|
`Bumping ${chalk.bold('expo.android.versionCode')} from ${chalk.bold(
|
||||||
versionCode
|
versionCode
|
||||||
@@ -105,7 +107,7 @@ export async function maybeResolveVersionsAsync(
|
|||||||
appBuildVersion:
|
appBuildVersion:
|
||||||
resolveConfigValue(buildGradle, 'versionCode', parsedGradleCommand?.flavor) ?? '1',
|
resolveConfigValue(buildGradle, 'versionCode', parsedGradleCommand?.flavor) ?? '1',
|
||||||
};
|
};
|
||||||
} catch (err: any) {
|
} catch {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -116,21 +118,33 @@ export async function maybeResolveVersionsAsync(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function writeVersionsToBuildGradleAsync({
|
export async function updateNativeVersionsAsync({
|
||||||
projectDir,
|
projectDir,
|
||||||
exp,
|
version,
|
||||||
|
versionCode,
|
||||||
}: {
|
}: {
|
||||||
projectDir: string;
|
projectDir: string;
|
||||||
exp: ExpoConfig;
|
version?: string;
|
||||||
}): Promise<string> {
|
versionCode?: number;
|
||||||
|
}): Promise<void> {
|
||||||
const buildGradle = await readBuildGradleAsync(projectDir);
|
const buildGradle = await readBuildGradleAsync(projectDir);
|
||||||
if (!buildGradle) {
|
if (!buildGradle) {
|
||||||
throw new Error('This project is missing a build.gradle file.');
|
throw new Error('This project is missing a build.gradle file.');
|
||||||
}
|
}
|
||||||
let updatedBuildGradle = AndroidConfig.Version.setVersionName(exp, buildGradle);
|
let updatedBuildGradle = buildGradle;
|
||||||
updatedBuildGradle = AndroidConfig.Version.setVersionCode(exp, updatedBuildGradle);
|
if (version !== undefined) {
|
||||||
|
updatedBuildGradle = updatedBuildGradle.replace(
|
||||||
|
new RegExp(`versionName ".*"`),
|
||||||
|
`versionName "${version}"`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (versionCode !== undefined) {
|
||||||
|
updatedBuildGradle = updatedBuildGradle.replace(
|
||||||
|
new RegExp(`versionCode.*`),
|
||||||
|
`versionCode ${versionCode}`
|
||||||
|
);
|
||||||
|
}
|
||||||
await writeBuildGradleAsync({ projectDir, buildGradle: updatedBuildGradle });
|
await writeBuildGradleAsync({ projectDir, buildGradle: updatedBuildGradle });
|
||||||
return updatedBuildGradle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function readBuildGradleAsync(projectDir: string): Promise<string | undefined> {
|
async function readBuildGradleAsync(projectDir: string): Promise<string | undefined> {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { getExpoWebsiteBaseUrl } from '../api';
|
|||||||
import {
|
import {
|
||||||
AppPlatform,
|
AppPlatform,
|
||||||
BuildFragment,
|
BuildFragment,
|
||||||
|
BuildParamsInput,
|
||||||
BuildPriority,
|
BuildPriority,
|
||||||
BuildStatus,
|
BuildStatus,
|
||||||
UploadSessionType,
|
UploadSessionType,
|
||||||
@@ -24,7 +25,7 @@ import {
|
|||||||
appPlatformEmojis,
|
appPlatformEmojis,
|
||||||
requestedPlatformDisplayNames,
|
requestedPlatformDisplayNames,
|
||||||
} from '../platform';
|
} from '../platform';
|
||||||
import { uploadAsync } from '../uploads';
|
import { uploadFileAtPathToS3Async } from '../uploads';
|
||||||
import { formatBytes } from '../utils/files';
|
import { formatBytes } from '../utils/files';
|
||||||
import { createProgressTracker } from '../utils/progress';
|
import { createProgressTracker } from '../utils/progress';
|
||||||
import { sleepAsync } from '../utils/promise';
|
import { sleepAsync } from '../utils/promise';
|
||||||
@@ -53,11 +54,22 @@ interface Builder<TPlatform extends Platform, Credentials, TJob extends Job> {
|
|||||||
): Promise<CredentialsResult<Credentials> | undefined>;
|
): Promise<CredentialsResult<Credentials> | undefined>;
|
||||||
syncProjectConfigurationAsync(ctx: BuildContext<TPlatform>): Promise<void>;
|
syncProjectConfigurationAsync(ctx: BuildContext<TPlatform>): Promise<void>;
|
||||||
prepareJobAsync(ctx: BuildContext<TPlatform>, jobData: JobData<Credentials>): Promise<Job>;
|
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>;
|
export type BuildRequestSender = () => Promise<BuildFragment | undefined>;
|
||||||
|
|
||||||
|
function resolveBuildParamsInput<T extends Platform>(ctx: BuildContext<T>): BuildParamsInput {
|
||||||
|
return {
|
||||||
|
resourceClass: ctx.resourceClass,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export async function prepareBuildRequestForPlatformAsync<
|
export async function prepareBuildRequestForPlatformAsync<
|
||||||
TPlatform extends Platform,
|
TPlatform extends Platform,
|
||||||
Credentials,
|
Credentials,
|
||||||
@@ -100,6 +112,7 @@ export async function prepareBuildRequestForPlatformAsync<
|
|||||||
} as const);
|
} as const);
|
||||||
|
|
||||||
const metadata = await collectMetadataAsync(ctx);
|
const metadata = await collectMetadataAsync(ctx);
|
||||||
|
const buildParams = resolveBuildParamsInput(ctx);
|
||||||
const job = await builder.prepareJobAsync(ctx, {
|
const job = await builder.prepareJobAsync(ctx, {
|
||||||
projectArchive,
|
projectArchive,
|
||||||
credentials: credentialsResult?.credentials,
|
credentials: credentialsResult?.credentials,
|
||||||
@@ -111,7 +124,7 @@ export async function prepareBuildRequestForPlatformAsync<
|
|||||||
return undefined;
|
return undefined;
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
return await sendBuildRequestAsync(builder, job, metadata);
|
return await sendBuildRequestAsync(builder, job, metadata, buildParams);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
handleBuildRequestError(error, job.platform);
|
handleBuildRequestError(error, job.platform);
|
||||||
}
|
}
|
||||||
@@ -157,10 +170,16 @@ async function uploadProjectAsync<TPlatform extends Platform>(
|
|||||||
try {
|
try {
|
||||||
return await withAnalyticsAsync(
|
return await withAnalyticsAsync(
|
||||||
async () => {
|
async () => {
|
||||||
|
Log.newLine();
|
||||||
|
Log.log(
|
||||||
|
`Compressing project files and uploading to EAS Build. ${learnMore(
|
||||||
|
'https://expo.fyi/eas-build-archive'
|
||||||
|
)}`
|
||||||
|
);
|
||||||
const projectTarball = await makeProjectTarballAsync();
|
const projectTarball = await makeProjectTarballAsync();
|
||||||
projectTarballPath = projectTarball.path;
|
projectTarballPath = projectTarball.path;
|
||||||
|
|
||||||
const { bucketKey } = await uploadAsync(
|
const { bucketKey } = await uploadFileAtPathToS3Async(
|
||||||
UploadSessionType.EasBuildProjectSources,
|
UploadSessionType.EasBuildProjectSources,
|
||||||
projectTarball.path,
|
projectTarball.path,
|
||||||
createProgressTracker({
|
createProgressTracker({
|
||||||
@@ -169,10 +188,7 @@ async function uploadProjectAsync<TPlatform extends Platform>(
|
|||||||
`Uploading to EAS Build (${formatBytes(projectTarball.size * ratio)} / ${formatBytes(
|
`Uploading to EAS Build (${formatBytes(projectTarball.size * ratio)} / ${formatBytes(
|
||||||
projectTarball.size
|
projectTarball.size
|
||||||
)})`,
|
)})`,
|
||||||
completedMessage: (duration: string) =>
|
completedMessage: (duration: string) => `Uploaded to EAS ${chalk.dim(duration)}`,
|
||||||
`Uploaded to EAS ${chalk.dim(duration)} ${learnMore(
|
|
||||||
'https://expo.fyi/eas-build-archive'
|
|
||||||
)}`,
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
return bucketKey;
|
return bucketKey;
|
||||||
@@ -194,7 +210,8 @@ async function uploadProjectAsync<TPlatform extends Platform>(
|
|||||||
async function sendBuildRequestAsync<TPlatform extends Platform, Credentials, TJob extends Job>(
|
async function sendBuildRequestAsync<TPlatform extends Platform, Credentials, TJob extends Job>(
|
||||||
builder: Builder<TPlatform, Credentials, TJob>,
|
builder: Builder<TPlatform, Credentials, TJob>,
|
||||||
job: TJob,
|
job: TJob,
|
||||||
metadata: Metadata
|
metadata: Metadata,
|
||||||
|
buildParams: BuildParamsInput
|
||||||
): Promise<BuildFragment> {
|
): Promise<BuildFragment> {
|
||||||
const { ctx } = builder;
|
const { ctx } = builder;
|
||||||
return await withAnalyticsAsync(
|
return await withAnalyticsAsync(
|
||||||
@@ -206,7 +223,8 @@ async function sendBuildRequestAsync<TPlatform extends Platform, Credentials, TJ
|
|||||||
const { build, deprecationInfo } = await builder.sendBuildRequestAsync(
|
const { build, deprecationInfo } = await builder.sendBuildRequestAsync(
|
||||||
ctx.projectId,
|
ctx.projectId,
|
||||||
job,
|
job,
|
||||||
metadata
|
metadata,
|
||||||
|
buildParams
|
||||||
);
|
);
|
||||||
|
|
||||||
printDeprecationWarnings(deprecationInfo);
|
printDeprecationWarnings(deprecationInfo);
|
||||||
@@ -231,16 +249,23 @@ export async function waitForBuildEndAsync(
|
|||||||
intervalSec = 10,
|
intervalSec = 10,
|
||||||
} = {}
|
} = {}
|
||||||
): Promise<MaybeBuildFragment[]> {
|
): Promise<MaybeBuildFragment[]> {
|
||||||
const b = `build${buildIds.length > 1 ? 's' : ''}`;
|
let spinner;
|
||||||
Log.log(`Waiting for ${b} to complete. You can press Ctrl+C to exit.`);
|
let originalSpinnerText;
|
||||||
const spinner = ora(`Waiting for ${b} to complete.`).start();
|
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;
|
const endTime = new Date().getTime() + timeoutSec * 1000;
|
||||||
while (new Date().getTime() <= endTime) {
|
while (new Date().getTime() <= endTime) {
|
||||||
const builds = await getBuildsSafelyAsync(buildIds);
|
const builds = await getBuildsSafelyAsync(buildIds);
|
||||||
const { refetch } =
|
const { refetch } =
|
||||||
builds.length === 1
|
builds.length === 1
|
||||||
? await handleSingleBuildProgressAsync({ build: builds[0], accountName }, { spinner })
|
? await handleSingleBuildProgressAsync({ build: builds[0], accountName }, { spinner })
|
||||||
: await handleMultipleBuildsProgressAsync({ builds }, { spinner });
|
: await handleMultipleBuildsProgressAsync({ builds }, { spinner, originalSpinnerText });
|
||||||
if (!refetch) {
|
if (!refetch) {
|
||||||
return builds;
|
return builds;
|
||||||
}
|
}
|
||||||
@@ -327,7 +352,7 @@ async function handleSingleBuildProgressAsync(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
Log.newLine();
|
Log.newLine();
|
||||||
Log.log('Waiting in queue');
|
Log.log(`Waiting in ${priorityToQueueDisplayName[build.priority]}`);
|
||||||
queueProgressBar.start(
|
queueProgressBar.start(
|
||||||
build.initialQueuePosition + 1,
|
build.initialQueuePosition + 1,
|
||||||
build.initialQueuePosition - build.queuePosition + 1,
|
build.initialQueuePosition - build.queuePosition + 1,
|
||||||
@@ -360,6 +385,12 @@ async function handleSingleBuildProgressAsync(
|
|||||||
return { refetch: true };
|
return { refetch: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const priorityToQueueDisplayName: Record<BuildPriority, string> = {
|
||||||
|
[BuildPriority.Normal]: 'queue',
|
||||||
|
[BuildPriority.NormalPlus]: 'queue',
|
||||||
|
[BuildPriority.High]: 'priority queue',
|
||||||
|
};
|
||||||
|
|
||||||
const statusToDisplayName: Record<BuildStatus, string> = {
|
const statusToDisplayName: Record<BuildStatus, string> = {
|
||||||
[BuildStatus.New]: 'waiting to enter the queue (concurrency limit reached)',
|
[BuildStatus.New]: 'waiting to enter the queue (concurrency limit reached)',
|
||||||
[BuildStatus.InQueue]: 'in queue',
|
[BuildStatus.InQueue]: 'in queue',
|
||||||
@@ -373,7 +404,7 @@ const platforms = [AppPlatform.Android, AppPlatform.Ios];
|
|||||||
|
|
||||||
async function handleMultipleBuildsProgressAsync(
|
async function handleMultipleBuildsProgressAsync(
|
||||||
{ builds: maybeBuilds }: { builds: MaybeBuildFragment[] },
|
{ builds: maybeBuilds }: { builds: MaybeBuildFragment[] },
|
||||||
{ spinner }: { spinner: Ora }
|
{ spinner, originalSpinnerText }: { spinner: Ora; originalSpinnerText: string }
|
||||||
): Promise<BuildProgressResult> {
|
): Promise<BuildProgressResult> {
|
||||||
const buildCount = maybeBuilds.length;
|
const buildCount = maybeBuilds.length;
|
||||||
const builds = maybeBuilds.filter<BuildFragment>(isBuildFragment);
|
const builds = maybeBuilds.filter<BuildFragment>(isBuildFragment);
|
||||||
@@ -393,7 +424,7 @@ async function handleMultipleBuildsProgressAsync(
|
|||||||
}
|
}
|
||||||
return { refetch: false };
|
return { refetch: false };
|
||||||
} else {
|
} else {
|
||||||
spinner.text = formatPendingBuildsText(builds);
|
spinner.text = formatPendingBuildsText(originalSpinnerText, builds);
|
||||||
return { refetch: true };
|
return { refetch: true };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -412,9 +443,10 @@ function formatSettledBuildsText(builds: BuildFragment[]): string {
|
|||||||
.join('\n ');
|
.join('\n ');
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatPendingBuildsText(builds: BuildFragment[]): string {
|
function formatPendingBuildsText(originalSpinnerText: string, builds: BuildFragment[]): string {
|
||||||
return platforms
|
return [
|
||||||
.map(platform => {
|
originalSpinnerText,
|
||||||
|
...platforms.map(platform => {
|
||||||
const build = builds.find(build => build.platform === platform);
|
const build = builds.find(build => build.platform === platform);
|
||||||
const status = build ? statusToDisplayName[build.status] : 'unknown';
|
const status = build ? statusToDisplayName[build.status] : 'unknown';
|
||||||
let extraInfo = '';
|
let extraInfo = '';
|
||||||
@@ -437,8 +469,8 @@ function formatPendingBuildsText(builds: BuildFragment[]): string {
|
|||||||
return `${appPlatformEmojis[platform]} ${
|
return `${appPlatformEmojis[platform]} ${
|
||||||
appPlatformDisplayNames[platform]
|
appPlatformDisplayNames[platform]
|
||||||
} build - status: ${chalk.bold(status)}${extraInfo}`;
|
} build - status: ${chalk.bold(status)}${extraInfo}`;
|
||||||
})
|
}),
|
||||||
.join('\n ');
|
].join('\n ');
|
||||||
}
|
}
|
||||||
|
|
||||||
function isBuildFragment(maybeBuild: MaybeBuildFragment): maybeBuild is BuildFragment {
|
function isBuildFragment(maybeBuild: MaybeBuildFragment): maybeBuild is BuildFragment {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { ExpoConfig } from '@expo/config';
|
import { ExpoConfig } from '@expo/config';
|
||||||
import { Platform, Workflow } from '@expo/eas-build-job';
|
import { Platform, Workflow } from '@expo/eas-build-job';
|
||||||
import { BuildProfile } from '@expo/eas-json';
|
import { BuildProfile, EasJson } from '@expo/eas-json';
|
||||||
import type { XCBuildConfiguration } from 'xcode';
|
|
||||||
|
|
||||||
import { TrackingContext } from '../analytics/common';
|
import { TrackingContext } from '../analytics/common';
|
||||||
import { CredentialsContext } from '../credentials/context';
|
import { CredentialsContext } from '../credentials/context';
|
||||||
import { Target } from '../credentials/ios/types';
|
import { Target } from '../credentials/ios/types';
|
||||||
|
import { BuildResourceClass } from '../graphql/generated';
|
||||||
import { GradleBuildContext } from '../project/android/gradle';
|
import { GradleBuildContext } from '../project/android/gradle';
|
||||||
import { XcodeBuildContext } from '../project/ios/scheme';
|
import { XcodeBuildContext } from '../project/ios/scheme';
|
||||||
import { Actor } from '../user/User';
|
import { Actor } from '../user/User';
|
||||||
@@ -20,7 +20,6 @@ export interface AndroidBuildContext {
|
|||||||
|
|
||||||
export interface IosBuildContext {
|
export interface IosBuildContext {
|
||||||
bundleIdentifier: string;
|
bundleIdentifier: string;
|
||||||
applicationTargetBuildSettings: XCBuildConfiguration['buildSettings'];
|
|
||||||
applicationTarget: Target;
|
applicationTarget: Target;
|
||||||
targets: Target[];
|
targets: Target[];
|
||||||
xcodeBuildContext: XcodeBuildContext;
|
xcodeBuildContext: XcodeBuildContext;
|
||||||
@@ -28,8 +27,10 @@ export interface IosBuildContext {
|
|||||||
|
|
||||||
export interface BuildContext<T extends Platform> {
|
export interface BuildContext<T extends Platform> {
|
||||||
accountName: string;
|
accountName: string;
|
||||||
|
easJsonCliConfig: EasJson['cli'];
|
||||||
buildProfile: BuildProfile<T>;
|
buildProfile: BuildProfile<T>;
|
||||||
buildProfileName: string;
|
buildProfileName: string;
|
||||||
|
resourceClass: BuildResourceClass;
|
||||||
clearCache: boolean;
|
clearCache: boolean;
|
||||||
credentialsCtx: CredentialsContext;
|
credentialsCtx: CredentialsContext;
|
||||||
exp: ExpoConfig;
|
exp: ExpoConfig;
|
||||||
@@ -39,6 +40,7 @@ export interface BuildContext<T extends Platform> {
|
|||||||
projectDir: string;
|
projectDir: string;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
projectName: string;
|
projectName: string;
|
||||||
|
message?: string;
|
||||||
trackingCtx: TrackingContext;
|
trackingCtx: TrackingContext;
|
||||||
user: Actor;
|
user: Actor;
|
||||||
workflow: Workflow;
|
workflow: Workflow;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Platform } from '@expo/eas-build-job';
|
import { Platform } from '@expo/eas-build-job';
|
||||||
import { BuildProfile } from '@expo/eas-json';
|
import { BuildProfile, EasJson } from '@expo/eas-json';
|
||||||
import JsonFile from '@expo/json-file';
|
import JsonFile from '@expo/json-file';
|
||||||
import resolveFrom from 'resolve-from';
|
import resolveFrom from 'resolve-from';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
@@ -7,6 +7,7 @@ import { v4 as uuidv4 } from 'uuid';
|
|||||||
import { TrackingContext } from '../analytics/common';
|
import { TrackingContext } from '../analytics/common';
|
||||||
import { Analytics, BuildEvent } from '../analytics/events';
|
import { Analytics, BuildEvent } from '../analytics/events';
|
||||||
import { CredentialsContext } from '../credentials/context';
|
import { CredentialsContext } from '../credentials/context';
|
||||||
|
import { BuildResourceClass } from '../graphql/generated';
|
||||||
import { getExpoConfig } from '../project/expoConfig';
|
import { getExpoConfig } from '../project/expoConfig';
|
||||||
import { getProjectAccountName, getProjectIdAsync } from '../project/projectUtils';
|
import { getProjectAccountName, getProjectIdAsync } from '../project/projectUtils';
|
||||||
import { resolveWorkflowAsync } from '../project/workflow';
|
import { resolveWorkflowAsync } from '../project/workflow';
|
||||||
@@ -20,19 +21,25 @@ import { LocalBuildOptions } from './local';
|
|||||||
export async function createBuildContextAsync<T extends Platform>({
|
export async function createBuildContextAsync<T extends Platform>({
|
||||||
buildProfileName,
|
buildProfileName,
|
||||||
buildProfile,
|
buildProfile,
|
||||||
|
easJsonCliConfig,
|
||||||
clearCache = false,
|
clearCache = false,
|
||||||
localBuildOptions,
|
localBuildOptions,
|
||||||
nonInteractive = false,
|
nonInteractive = false,
|
||||||
platform,
|
platform,
|
||||||
projectDir,
|
projectDir,
|
||||||
|
resourceClass,
|
||||||
|
message,
|
||||||
}: {
|
}: {
|
||||||
buildProfileName: string;
|
buildProfileName: string;
|
||||||
buildProfile: BuildProfile<T>;
|
buildProfile: BuildProfile<T>;
|
||||||
|
easJsonCliConfig: EasJson['cli'];
|
||||||
clearCache: boolean;
|
clearCache: boolean;
|
||||||
localBuildOptions: LocalBuildOptions;
|
localBuildOptions: LocalBuildOptions;
|
||||||
nonInteractive: boolean;
|
nonInteractive: boolean;
|
||||||
platform: T;
|
platform: T;
|
||||||
projectDir: string;
|
projectDir: string;
|
||||||
|
resourceClass: BuildResourceClass;
|
||||||
|
message?: string;
|
||||||
}): Promise<BuildContext<T>> {
|
}): Promise<BuildContext<T>> {
|
||||||
const exp = getExpoConfig(projectDir, { env: buildProfile.env });
|
const exp = getExpoConfig(projectDir, { env: buildProfile.env });
|
||||||
|
|
||||||
@@ -70,6 +77,8 @@ export async function createBuildContextAsync<T extends Platform>({
|
|||||||
accountName,
|
accountName,
|
||||||
buildProfile,
|
buildProfile,
|
||||||
buildProfileName,
|
buildProfileName,
|
||||||
|
resourceClass,
|
||||||
|
easJsonCliConfig,
|
||||||
clearCache,
|
clearCache,
|
||||||
credentialsCtx,
|
credentialsCtx,
|
||||||
exp,
|
exp,
|
||||||
@@ -82,6 +91,7 @@ export async function createBuildContextAsync<T extends Platform>({
|
|||||||
trackingCtx,
|
trackingCtx,
|
||||||
user,
|
user,
|
||||||
workflow,
|
workflow,
|
||||||
|
message,
|
||||||
};
|
};
|
||||||
if (platform === Platform.ANDROID) {
|
if (platform === Platform.ANDROID) {
|
||||||
const common = commonContext as CommonContext<Platform.ANDROID>;
|
const common = commonContext as CommonContext<Platform.ANDROID>;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { IOSConfig } from '@expo/config-plugins';
|
|||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import { vol } from 'memfs';
|
import { vol } from 'memfs';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
import type { XCBuildConfiguration } from 'xcode';
|
||||||
|
|
||||||
import { readPlistAsync } from '../../../utils/plist';
|
import { readPlistAsync } from '../../../utils/plist';
|
||||||
import {
|
import {
|
||||||
@@ -17,6 +18,12 @@ import {
|
|||||||
|
|
||||||
jest.mock('fs');
|
jest.mock('fs');
|
||||||
|
|
||||||
|
const getXCBuildConfigurationFromPbxproj = jest.spyOn(
|
||||||
|
IOSConfig.Target,
|
||||||
|
'getXCBuildConfigurationFromPbxproj'
|
||||||
|
);
|
||||||
|
const getPbxproj = jest.spyOn(IOSConfig.XcodeUtils, 'getPbxproj');
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
// do not remove the following line
|
// do not remove the following line
|
||||||
// this fixes a weird error with tempy in @expo/image-utils
|
// this fixes a weird error with tempy in @expo/image-utils
|
||||||
@@ -51,14 +58,34 @@ describe(evaluateTemplateString, () => {
|
|||||||
|
|
||||||
// bare workflow
|
// bare workflow
|
||||||
describe(bumpVersionAsync, () => {
|
describe(bumpVersionAsync, () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
getPbxproj.mockImplementation(() => ({} as any));
|
||||||
|
});
|
||||||
|
afterEach(() => {
|
||||||
|
getXCBuildConfigurationFromPbxproj.mockReset();
|
||||||
|
getPbxproj.mockReset();
|
||||||
|
});
|
||||||
it('bumps expo.ios.buildNumber and CFBundleVersion when strategy = BumpStrategy.BUILD_NUMBER', async () => {
|
it('bumps expo.ios.buildNumber and CFBundleVersion when strategy = BumpStrategy.BUILD_NUMBER', async () => {
|
||||||
const fakeExp = initBareWorkflowProject();
|
const fakeExp = initBareWorkflowProject();
|
||||||
|
getXCBuildConfigurationFromPbxproj.mockImplementation(
|
||||||
|
() =>
|
||||||
|
({
|
||||||
|
buildSettings: {
|
||||||
|
INFOPLIST_FILE: 'myproject/Info.plist',
|
||||||
|
},
|
||||||
|
} as XCBuildConfiguration)
|
||||||
|
);
|
||||||
await bumpVersionAsync({
|
await bumpVersionAsync({
|
||||||
bumpStrategy: BumpStrategy.BUILD_NUMBER,
|
bumpStrategy: BumpStrategy.BUILD_NUMBER,
|
||||||
projectDir: '/repo',
|
projectDir: '/repo',
|
||||||
exp: fakeExp,
|
exp: fakeExp,
|
||||||
buildSettings: {},
|
targets: [
|
||||||
|
{
|
||||||
|
targetName: 'example',
|
||||||
|
bundleIdentifier: 'example.com',
|
||||||
|
entitlements: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const appJSON = await fs.readJSON('/repo/app.json');
|
const appJSON = await fs.readJSON('/repo/app.json');
|
||||||
@@ -76,13 +103,25 @@ describe(bumpVersionAsync, () => {
|
|||||||
it('bumps expo.ios.buildNumber and CFBundleVersion for non default Info.plist location', async () => {
|
it('bumps expo.ios.buildNumber and CFBundleVersion for non default Info.plist location', async () => {
|
||||||
const fakeExp = initBareWorkflowProject({ infoPlistName: 'Info2.plist' });
|
const fakeExp = initBareWorkflowProject({ infoPlistName: 'Info2.plist' });
|
||||||
|
|
||||||
|
getXCBuildConfigurationFromPbxproj.mockImplementation(
|
||||||
|
() =>
|
||||||
|
({
|
||||||
|
buildSettings: {
|
||||||
|
INFOPLIST_FILE: '$(SRCROOT)/myproject/Info2.plist',
|
||||||
|
},
|
||||||
|
} as XCBuildConfiguration)
|
||||||
|
);
|
||||||
await bumpVersionAsync({
|
await bumpVersionAsync({
|
||||||
bumpStrategy: BumpStrategy.BUILD_NUMBER,
|
bumpStrategy: BumpStrategy.BUILD_NUMBER,
|
||||||
projectDir: '/repo',
|
projectDir: '/repo',
|
||||||
exp: fakeExp,
|
exp: fakeExp,
|
||||||
buildSettings: {
|
targets: [
|
||||||
INFOPLIST_FILE: '$(SRCROOT)/myproject/Info2.plist',
|
{
|
||||||
},
|
targetName: 'example',
|
||||||
|
bundleIdentifier: 'example.com',
|
||||||
|
entitlements: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const appJSON = await fs.readJSON('/repo/app.json');
|
const appJSON = await fs.readJSON('/repo/app.json');
|
||||||
@@ -97,14 +136,27 @@ describe(bumpVersionAsync, () => {
|
|||||||
expect(infoPlist['CFBundleVersion']).toBe('2');
|
expect(infoPlist['CFBundleVersion']).toBe('2');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('bumps expo.version and CFBundleShortVersionString when strategy = BumpStrategy.SHORT_VERSION', async () => {
|
it('bumps expo.version and CFBundleShortVersionString when strategy = BumpStrategy.APP_VERSION', async () => {
|
||||||
const fakeExp = initBareWorkflowProject();
|
const fakeExp = initBareWorkflowProject();
|
||||||
|
getXCBuildConfigurationFromPbxproj.mockImplementation(
|
||||||
|
() =>
|
||||||
|
({
|
||||||
|
buildSettings: {
|
||||||
|
INFOPLIST_FILE: 'myproject/Info.plist',
|
||||||
|
},
|
||||||
|
} as XCBuildConfiguration)
|
||||||
|
);
|
||||||
await bumpVersionAsync({
|
await bumpVersionAsync({
|
||||||
bumpStrategy: BumpStrategy.APP_VERSION,
|
bumpStrategy: BumpStrategy.APP_VERSION,
|
||||||
projectDir: '/repo',
|
projectDir: '/repo',
|
||||||
exp: fakeExp,
|
exp: fakeExp,
|
||||||
buildSettings: {},
|
targets: [
|
||||||
|
{
|
||||||
|
targetName: 'example',
|
||||||
|
bundleIdentifier: 'example.com',
|
||||||
|
entitlements: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const appJSON = await fs.readJSON('/repo/app.json');
|
const appJSON = await fs.readJSON('/repo/app.json');
|
||||||
@@ -121,12 +173,25 @@ describe(bumpVersionAsync, () => {
|
|||||||
|
|
||||||
it('does not bump any version when strategy = BumpStrategy.NOOP', async () => {
|
it('does not bump any version when strategy = BumpStrategy.NOOP', async () => {
|
||||||
const fakeExp = initBareWorkflowProject();
|
const fakeExp = initBareWorkflowProject();
|
||||||
|
getXCBuildConfigurationFromPbxproj.mockImplementation(
|
||||||
|
() =>
|
||||||
|
({
|
||||||
|
buildSettings: {
|
||||||
|
INFOPLIST_FILE: 'myproject/Info.plist',
|
||||||
|
},
|
||||||
|
} as XCBuildConfiguration)
|
||||||
|
);
|
||||||
await bumpVersionAsync({
|
await bumpVersionAsync({
|
||||||
bumpStrategy: BumpStrategy.NOOP,
|
bumpStrategy: BumpStrategy.NOOP,
|
||||||
projectDir: '/repo',
|
projectDir: '/repo',
|
||||||
exp: fakeExp,
|
exp: fakeExp,
|
||||||
buildSettings: {},
|
targets: [
|
||||||
|
{
|
||||||
|
targetName: 'example',
|
||||||
|
bundleIdentifier: 'example.com',
|
||||||
|
entitlements: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const appJSON = await fs.readJSON('/repo/app.json');
|
const appJSON = await fs.readJSON('/repo/app.json');
|
||||||
@@ -288,9 +353,9 @@ describe(getInfoPlistPath, () => {
|
|||||||
|
|
||||||
function initBareWorkflowProject({
|
function initBareWorkflowProject({
|
||||||
appVersion = '1.0.0',
|
appVersion = '1.0.0',
|
||||||
version = '1',
|
buildNumber = '1',
|
||||||
infoPlistName = 'Info.plist',
|
infoPlistName = 'Info.plist',
|
||||||
}: { appVersion?: string; version?: string; infoPlistName?: string } = {}): ExpoConfig {
|
}: { appVersion?: string; buildNumber?: string; infoPlistName?: string } = {}): ExpoConfig {
|
||||||
const fakeExp: ExpoConfig = {
|
const fakeExp: ExpoConfig = {
|
||||||
name: 'myproject',
|
name: 'myproject',
|
||||||
slug: 'myproject',
|
slug: 'myproject',
|
||||||
@@ -311,7 +376,7 @@ function initBareWorkflowProject({
|
|||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>${appVersion}</string>
|
<string>${appVersion}</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>${version}</string>
|
<string>${buildNumber}</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>`,
|
</plist>`,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { IOSConfig } from '@expo/config-plugins';
|
|
||||||
import { Ios, Job, Metadata, Platform, Workflow } from '@expo/eas-build-job';
|
import { Ios, Job, Metadata, Platform, Workflow } from '@expo/eas-build-job';
|
||||||
import type { XCBuildConfiguration } from 'xcode';
|
|
||||||
|
|
||||||
import { IosCredentials, Target } from '../../credentials/ios/types';
|
import { IosCredentials } from '../../credentials/ios/types';
|
||||||
|
import { BuildParamsInput } from '../../graphql/generated';
|
||||||
import { BuildMutation, BuildResult } from '../../graphql/mutations/BuildMutation';
|
import { BuildMutation, BuildResult } from '../../graphql/mutations/BuildMutation';
|
||||||
import { ensureBundleIdentifierIsDefinedForManagedProjectAsync } from '../../project/ios/bundleIdentifier';
|
import { ensureBundleIdentifierIsDefinedForManagedProjectAsync } from '../../project/ios/bundleIdentifier';
|
||||||
import { resolveXcodeBuildContextAsync } from '../../project/ios/scheme';
|
import { resolveXcodeBuildContextAsync } from '../../project/ios/scheme';
|
||||||
@@ -43,12 +42,10 @@ export async function createIosContextAsync(
|
|||||||
env: buildProfile.env,
|
env: buildProfile.env,
|
||||||
});
|
});
|
||||||
const applicationTarget = findApplicationTarget(targets);
|
const applicationTarget = findApplicationTarget(targets);
|
||||||
const applicationTargetBuildSettings = resolveBuildSettings(ctx, applicationTarget);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
bundleIdentifier: applicationTarget.bundleIdentifier,
|
bundleIdentifier: applicationTarget.bundleIdentifier,
|
||||||
applicationTarget,
|
applicationTarget,
|
||||||
applicationTargetBuildSettings,
|
|
||||||
targets,
|
targets,
|
||||||
xcodeBuildContext,
|
xcodeBuildContext,
|
||||||
};
|
};
|
||||||
@@ -67,7 +64,7 @@ export async function prepareIosBuildAsync(
|
|||||||
projectDir: ctx.projectDir,
|
projectDir: ctx.projectDir,
|
||||||
exp: ctx.exp,
|
exp: ctx.exp,
|
||||||
buildProfile: ctx.buildProfile,
|
buildProfile: ctx.buildProfile,
|
||||||
buildSettings: ctx.ios.applicationTargetBuildSettings,
|
targets: ctx.ios.targets,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
prepareJobAsync: async (
|
prepareJobAsync: async (
|
||||||
@@ -82,7 +79,8 @@ export async function prepareIosBuildAsync(
|
|||||||
sendBuildRequestAsync: async (
|
sendBuildRequestAsync: async (
|
||||||
appId: string,
|
appId: string,
|
||||||
job: Ios.Job,
|
job: Ios.Job,
|
||||||
metadata: Metadata
|
metadata: Metadata,
|
||||||
|
buildParams: BuildParamsInput
|
||||||
): Promise<BuildResult> => {
|
): Promise<BuildResult> => {
|
||||||
const graphqlMetadata = transformMetadata(metadata);
|
const graphqlMetadata = transformMetadata(metadata);
|
||||||
const graphqlJob = transformJob(job);
|
const graphqlJob = transformJob(job);
|
||||||
@@ -90,22 +88,8 @@ export async function prepareIosBuildAsync(
|
|||||||
appId,
|
appId,
|
||||||
job: graphqlJob,
|
job: graphqlJob,
|
||||||
metadata: graphqlMetadata,
|
metadata: graphqlMetadata,
|
||||||
|
buildParams,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveBuildSettings(
|
|
||||||
ctx: CommonContext<Platform.IOS>,
|
|
||||||
applicationTarget: Target
|
|
||||||
): XCBuildConfiguration['buildSettings'] {
|
|
||||||
if (ctx.workflow === Workflow.MANAGED) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
const project = IOSConfig.XcodeUtils.getPbxproj(ctx.projectDir);
|
|
||||||
const xcBuildConfiguration = IOSConfig.Target.getXCBuildConfigurationFromPbxproj(project, {
|
|
||||||
targetName: applicationTarget.targetName,
|
|
||||||
buildConfiguration: applicationTarget.buildConfiguration,
|
|
||||||
});
|
|
||||||
return xcBuildConfiguration?.buildSettings ?? {};
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { ExpoConfig } from '@expo/config';
|
import { ExpoConfig } from '@expo/config';
|
||||||
import { Platform, Workflow } from '@expo/eas-build-job';
|
import { Platform, Workflow } from '@expo/eas-build-job';
|
||||||
import { BuildProfile, IosVersionAutoIncrement } from '@expo/eas-json';
|
import { BuildProfile, IosVersionAutoIncrement } from '@expo/eas-json';
|
||||||
import type { XCBuildConfiguration } from 'xcode';
|
|
||||||
|
|
||||||
|
import { Target } from '../../credentials/ios/types';
|
||||||
import { isExpoUpdatesInstalled } from '../../project/projectUtils';
|
import { isExpoUpdatesInstalled } from '../../project/projectUtils';
|
||||||
import { resolveWorkflowAsync } from '../../project/workflow';
|
import { resolveWorkflowAsync } from '../../project/workflow';
|
||||||
import { syncUpdatesConfigurationAsync } from '../../update/ios/UpdatesModule';
|
import { syncUpdatesConfigurationAsync } from '../../update/ios/UpdatesModule';
|
||||||
@@ -12,12 +12,12 @@ export async function syncProjectConfigurationAsync({
|
|||||||
projectDir,
|
projectDir,
|
||||||
exp,
|
exp,
|
||||||
buildProfile,
|
buildProfile,
|
||||||
buildSettings,
|
targets,
|
||||||
}: {
|
}: {
|
||||||
projectDir: string;
|
projectDir: string;
|
||||||
exp: ExpoConfig;
|
exp: ExpoConfig;
|
||||||
buildProfile: BuildProfile<Platform.IOS>;
|
buildProfile: BuildProfile<Platform.IOS>;
|
||||||
buildSettings: XCBuildConfiguration['buildSettings'];
|
targets: Target[];
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
const workflow = await resolveWorkflowAsync(projectDir, Platform.IOS);
|
const workflow = await resolveWorkflowAsync(projectDir, Platform.IOS);
|
||||||
const { autoIncrement } = buildProfile;
|
const { autoIncrement } = buildProfile;
|
||||||
@@ -27,7 +27,7 @@ export async function syncProjectConfigurationAsync({
|
|||||||
if (isExpoUpdatesInstalled(projectDir)) {
|
if (isExpoUpdatesInstalled(projectDir)) {
|
||||||
await syncUpdatesConfigurationAsync(projectDir, exp);
|
await syncUpdatesConfigurationAsync(projectDir, exp);
|
||||||
}
|
}
|
||||||
await bumpVersionAsync({ projectDir, exp, bumpStrategy: versionBumpStrategy, buildSettings });
|
await bumpVersionAsync({ projectDir, exp, bumpStrategy: versionBumpStrategy, targets });
|
||||||
} else {
|
} else {
|
||||||
await bumpVersionInAppJsonAsync({ projectDir, exp, bumpStrategy: versionBumpStrategy });
|
await bumpVersionInAppJsonAsync({ projectDir, exp, bumpStrategy: versionBumpStrategy });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,20 @@
|
|||||||
import { ExpoConfig, getConfigFilePaths } from '@expo/config';
|
import { ExpoConfig } from '@expo/config';
|
||||||
import { IOSConfig } from '@expo/config-plugins';
|
import { IOSConfig } from '@expo/config-plugins';
|
||||||
import { Platform, Workflow } from '@expo/eas-build-job';
|
import { Platform, Workflow } from '@expo/eas-build-job';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import type { XCBuildConfiguration } from 'xcode';
|
import type { XCBuildConfiguration } from 'xcode';
|
||||||
|
|
||||||
|
import { Target } from '../../credentials/ios/types';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
|
import { findApplicationTarget } from '../../project/ios/target';
|
||||||
|
import { getNextBuildNumber, isValidBuildNumber } from '../../project/ios/versions';
|
||||||
import { resolveWorkflowAsync } from '../../project/workflow';
|
import { resolveWorkflowAsync } from '../../project/workflow';
|
||||||
import { promptAsync } from '../../prompts';
|
import { promptAsync } from '../../prompts';
|
||||||
|
import uniqBy from '../../utils/expodash/uniqBy';
|
||||||
import { readPlistAsync, writePlistAsync } from '../../utils/plist';
|
import { readPlistAsync, writePlistAsync } from '../../utils/plist';
|
||||||
import { updateAppJsonConfigAsync } from '../utils/appJson';
|
import { updateAppJsonConfigAsync } from '../utils/appJson';
|
||||||
import { bumpAppVersionAsync } from '../utils/version';
|
import { bumpAppVersionAsync, ensureStaticConfigExists } from '../utils/version';
|
||||||
|
|
||||||
export enum BumpStrategy {
|
export enum BumpStrategy {
|
||||||
APP_VERSION,
|
APP_VERSION,
|
||||||
@@ -22,21 +26,25 @@ export async function bumpVersionAsync({
|
|||||||
bumpStrategy,
|
bumpStrategy,
|
||||||
projectDir,
|
projectDir,
|
||||||
exp,
|
exp,
|
||||||
buildSettings,
|
targets,
|
||||||
}: {
|
}: {
|
||||||
projectDir: string;
|
projectDir: string;
|
||||||
exp: ExpoConfig;
|
exp: ExpoConfig;
|
||||||
bumpStrategy: BumpStrategy;
|
bumpStrategy: BumpStrategy;
|
||||||
buildSettings: XCBuildConfiguration['buildSettings'];
|
targets: Target[];
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
if (bumpStrategy === BumpStrategy.NOOP) {
|
if (bumpStrategy === BumpStrategy.NOOP) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ensureStaticConfigExists(projectDir);
|
ensureStaticConfigExists(projectDir);
|
||||||
const infoPlist = await readInfoPlistAsync(projectDir, buildSettings);
|
|
||||||
await bumpVersionInAppJsonAsync({ bumpStrategy, projectDir, exp });
|
await bumpVersionInAppJsonAsync({ bumpStrategy, projectDir, exp });
|
||||||
Log.log('Updated versions in app.json');
|
Log.log('Updated versions in app.json');
|
||||||
await writeVersionsToInfoPlistAsync({ projectDir, exp, infoPlist, buildSettings });
|
await updateNativeVersionsAsync({
|
||||||
|
projectDir,
|
||||||
|
version: exp.version,
|
||||||
|
buildNumber: exp.ios?.buildNumber,
|
||||||
|
targets,
|
||||||
|
});
|
||||||
Log.log('Synchronized versions with Info.plist');
|
Log.log('Synchronized versions with Info.plist');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,10 +67,8 @@ export async function bumpVersionInAppJsonAsync({
|
|||||||
await bumpAppVersionAsync({ appVersion, projectDir, exp });
|
await bumpAppVersionAsync({ appVersion, projectDir, exp });
|
||||||
} else {
|
} else {
|
||||||
const buildNumber = IOSConfig.Version.getBuildNumber(exp);
|
const buildNumber = IOSConfig.Version.getBuildNumber(exp);
|
||||||
if (buildNumber.match(/^\d+(\.\d+)*$/)) {
|
if (isValidBuildNumber(buildNumber)) {
|
||||||
const comps = buildNumber.split('.');
|
const bumpedBuildNumber = getNextBuildNumber(buildNumber);
|
||||||
comps[comps.length - 1] = String(Number(comps[comps.length - 1]) + 1);
|
|
||||||
const bumpedBuildNumber = comps.join('.');
|
|
||||||
Log.log(
|
Log.log(
|
||||||
`Bumping ${chalk.bold('expo.ios.buildNumber')} from ${chalk.bold(
|
`Bumping ${chalk.bold('expo.ios.buildNumber')} from ${chalk.bold(
|
||||||
buildNumber
|
buildNumber
|
||||||
@@ -121,12 +127,21 @@ export async function readBuildNumberAsync(
|
|||||||
export async function maybeResolveVersionsAsync(
|
export async function maybeResolveVersionsAsync(
|
||||||
projectDir: string,
|
projectDir: string,
|
||||||
exp: ExpoConfig,
|
exp: ExpoConfig,
|
||||||
buildSettings: XCBuildConfiguration['buildSettings']
|
targets: Target[]
|
||||||
): Promise<{ appVersion?: string; appBuildVersion?: string }> {
|
): Promise<{ appVersion?: string; appBuildVersion?: string }> {
|
||||||
|
const applicationTarget = findApplicationTarget(targets);
|
||||||
try {
|
try {
|
||||||
return {
|
return {
|
||||||
appBuildVersion: await readBuildNumberAsync(projectDir, exp, buildSettings),
|
appBuildVersion: await readBuildNumberAsync(
|
||||||
appVersion: await readShortVersionAsync(projectDir, exp, buildSettings),
|
projectDir,
|
||||||
|
exp,
|
||||||
|
applicationTarget.buildSettings ?? {}
|
||||||
|
),
|
||||||
|
appVersion: await readShortVersionAsync(
|
||||||
|
projectDir,
|
||||||
|
exp,
|
||||||
|
applicationTarget.buildSettings ?? {}
|
||||||
|
),
|
||||||
};
|
};
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
Log.warn('Failed to read app versions.');
|
Log.warn('Failed to read app versions.');
|
||||||
@@ -137,23 +152,6 @@ export async function maybeResolveVersionsAsync(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function writeVersionsToInfoPlistAsync({
|
|
||||||
projectDir,
|
|
||||||
exp,
|
|
||||||
infoPlist,
|
|
||||||
buildSettings,
|
|
||||||
}: {
|
|
||||||
projectDir: string;
|
|
||||||
exp: ExpoConfig;
|
|
||||||
infoPlist: IOSConfig.InfoPlist;
|
|
||||||
buildSettings: XCBuildConfiguration['buildSettings'];
|
|
||||||
}): Promise<IOSConfig.InfoPlist> {
|
|
||||||
let updatedInfoPlist = IOSConfig.Version.setVersion(exp, infoPlist);
|
|
||||||
updatedInfoPlist = IOSConfig.Version.setBuildNumber(exp, updatedInfoPlist);
|
|
||||||
await writeInfoPlistAsync({ projectDir, infoPlist: updatedInfoPlist, buildSettings });
|
|
||||||
return updatedInfoPlist;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getInfoPlistPath(
|
export function getInfoPlistPath(
|
||||||
projectDir: string,
|
projectDir: string,
|
||||||
buildSettings: XCBuildConfiguration['buildSettings']
|
buildSettings: XCBuildConfiguration['buildSettings']
|
||||||
@@ -181,24 +179,55 @@ async function readInfoPlistAsync(
|
|||||||
return ((await readPlistAsync(infoPlistPath)) ?? {}) as IOSConfig.InfoPlist;
|
return ((await readPlistAsync(infoPlistPath)) ?? {}) as IOSConfig.InfoPlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function writeInfoPlistAsync({
|
export async function updateNativeVersionsAsync({
|
||||||
projectDir,
|
projectDir,
|
||||||
infoPlist,
|
version,
|
||||||
buildSettings,
|
buildNumber,
|
||||||
|
targets,
|
||||||
}: {
|
}: {
|
||||||
projectDir: string;
|
projectDir: string;
|
||||||
infoPlist: IOSConfig.InfoPlist;
|
version?: string;
|
||||||
buildSettings: XCBuildConfiguration['buildSettings'];
|
buildNumber?: string;
|
||||||
|
targets: Target[];
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
const infoPlistPath = getInfoPlistPath(projectDir, buildSettings);
|
const project = IOSConfig.XcodeUtils.getPbxproj(projectDir);
|
||||||
await writePlistAsync(infoPlistPath, infoPlist);
|
const iosDir = path.join(projectDir, 'ios');
|
||||||
|
|
||||||
|
const infoPlistFiles: string[] = [];
|
||||||
|
for (const target of targets) {
|
||||||
|
const { targetName, buildConfiguration } = target;
|
||||||
|
const xcBuildConfiguration = IOSConfig.Target.getXCBuildConfigurationFromPbxproj(project, {
|
||||||
|
targetName,
|
||||||
|
buildConfiguration,
|
||||||
|
});
|
||||||
|
const infoPlist = xcBuildConfiguration?.buildSettings?.INFOPLIST_FILE;
|
||||||
|
if (infoPlist) {
|
||||||
|
const evaluatedInfoPlistPath = trimQuotes(
|
||||||
|
evaluateTemplateString(infoPlist, {
|
||||||
|
SRCROOT: iosDir,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const absolutePath = path.isAbsolute(evaluatedInfoPlistPath)
|
||||||
|
? evaluatedInfoPlistPath
|
||||||
|
: path.join(iosDir, evaluatedInfoPlistPath);
|
||||||
|
infoPlistFiles.push(path.normalize(absolutePath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const uniqueInfoPlistPaths = uniqBy(infoPlistFiles, i => i);
|
||||||
|
for (const infoPlistPath of uniqueInfoPlistPaths) {
|
||||||
|
const infoPlist = (await readPlistAsync(infoPlistPath)) as IOSConfig.InfoPlist;
|
||||||
|
if (buildNumber) {
|
||||||
|
infoPlist.CFBundleVersion = buildNumber;
|
||||||
|
}
|
||||||
|
if (version) {
|
||||||
|
infoPlist.CFBundleShortVersionString = version;
|
||||||
|
}
|
||||||
|
await writePlistAsync(infoPlistPath, infoPlist);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function ensureStaticConfigExists(projectDir: string): void {
|
function trimQuotes(s: string): string {
|
||||||
const paths = getConfigFilePaths(projectDir);
|
return s?.startsWith('"') && s.endsWith('"') ? s.slice(1, -1) : s;
|
||||||
if (!paths.staticConfigPath) {
|
|
||||||
throw new Error('autoIncrement option is not supported when using app.config.js');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function evaluateTemplateString(
|
export function evaluateTemplateString(
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import semver from 'semver';
|
|||||||
import { ora } from '../ora';
|
import { ora } from '../ora';
|
||||||
|
|
||||||
const PLUGIN_PACKAGE_NAME = 'eas-cli-local-build-plugin';
|
const PLUGIN_PACKAGE_NAME = 'eas-cli-local-build-plugin';
|
||||||
const PLUGIN_PACKAGE_VERSION = '0.0.78';
|
const PLUGIN_PACKAGE_VERSION = '0.0.85';
|
||||||
|
|
||||||
export interface LocalBuildOptions {
|
export interface LocalBuildOptions {
|
||||||
enable: boolean;
|
enable: boolean;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
import { ensureLoggedInAsync } from '../user/actions';
|
import { ensureLoggedInAsync } from '../user/actions';
|
||||||
import { easCliVersion } from '../utils/easCli';
|
import { easCliVersion } from '../utils/easCli';
|
||||||
import { getVcsClient } from '../vcs';
|
import { getVcsClient } from '../vcs';
|
||||||
|
import { Client } from '../vcs/vcs';
|
||||||
import { maybeResolveVersionsAsync as maybeResolveAndroidVersionsAsync } from './android/version';
|
import { maybeResolveVersionsAsync as maybeResolveAndroidVersionsAsync } from './android/version';
|
||||||
import { BuildContext } from './context';
|
import { BuildContext } from './context';
|
||||||
import { maybeResolveVersionsAsync as maybeResolveIosVersionsAsync } from './ios/version';
|
import { maybeResolveVersionsAsync as maybeResolveIosVersionsAsync } from './ios/version';
|
||||||
@@ -29,7 +30,9 @@ export async function collectMetadataAsync<T extends Platform>(
|
|||||||
('simulator' in ctx.buildProfile && ctx.buildProfile.simulator
|
('simulator' in ctx.buildProfile && ctx.buildProfile.simulator
|
||||||
? 'simulator'
|
? 'simulator'
|
||||||
: ctx.buildProfile.distribution) ?? 'store';
|
: ctx.buildProfile.distribution) ?? 'store';
|
||||||
const metadata = {
|
|
||||||
|
const vcsClient = getVcsClient();
|
||||||
|
const metadata: Metadata = {
|
||||||
trackingContext: ctx.trackingCtx,
|
trackingContext: ctx.trackingCtx,
|
||||||
...(await maybeResolveVersionsAsync(ctx)),
|
...(await maybeResolveVersionsAsync(ctx)),
|
||||||
cliVersion: easCliVersion,
|
cliVersion: easCliVersion,
|
||||||
@@ -43,9 +46,10 @@ export async function collectMetadataAsync<T extends Platform>(
|
|||||||
appName: ctx.exp.name,
|
appName: ctx.exp.name,
|
||||||
appIdentifier: resolveAppIdentifier(ctx),
|
appIdentifier: resolveAppIdentifier(ctx),
|
||||||
buildProfile: ctx.buildProfileName,
|
buildProfile: ctx.buildProfileName,
|
||||||
gitCommitHash: await getVcsClient().getCommitHashAsync(),
|
gitCommitHash: await vcsClient.getCommitHashAsync(),
|
||||||
isGitWorkingTreeDirty: await getVcsClient().hasUncommittedChangesAsync(),
|
isGitWorkingTreeDirty: await vcsClient.hasUncommittedChangesAsync(),
|
||||||
username: getUsername(ctx.exp, await ensureLoggedInAsync()),
|
username: getUsername(ctx.exp, await ensureLoggedInAsync()),
|
||||||
|
message: ctx.message ?? (await getFormattedCommitMessageAsync(vcsClient)),
|
||||||
...(ctx.platform === Platform.IOS && {
|
...(ctx.platform === Platform.IOS && {
|
||||||
iosEnterpriseProvisioning: resolveIosEnterpriseProvisioning(
|
iosEnterpriseProvisioning: resolveIosEnterpriseProvisioning(
|
||||||
ctx as BuildContext<Platform.IOS>
|
ctx as BuildContext<Platform.IOS>
|
||||||
@@ -60,11 +64,7 @@ async function maybeResolveVersionsAsync<T extends Platform>(
|
|||||||
): Promise<{ appBuildVersion?: string; appVersion?: string }> {
|
): Promise<{ appBuildVersion?: string; appVersion?: string }> {
|
||||||
if (ctx.platform === Platform.IOS) {
|
if (ctx.platform === Platform.IOS) {
|
||||||
const iosContext = ctx as BuildContext<Platform.IOS>;
|
const iosContext = ctx as BuildContext<Platform.IOS>;
|
||||||
return await maybeResolveIosVersionsAsync(
|
return await maybeResolveIosVersionsAsync(ctx.projectDir, ctx.exp, iosContext.ios.targets);
|
||||||
ctx.projectDir,
|
|
||||||
ctx.exp,
|
|
||||||
iosContext.ios.applicationTargetBuildSettings
|
|
||||||
);
|
|
||||||
} else if (ctx.platform === Platform.ANDROID) {
|
} else if (ctx.platform === Platform.ANDROID) {
|
||||||
const androidCtx = ctx as BuildContext<Platform.ANDROID>;
|
const androidCtx = ctx as BuildContext<Platform.ANDROID>;
|
||||||
return await maybeResolveAndroidVersionsAsync(ctx.projectDir, ctx.exp, androidCtx.buildProfile);
|
return await maybeResolveAndroidVersionsAsync(ctx.projectDir, ctx.exp, androidCtx.buildProfile);
|
||||||
@@ -149,3 +149,16 @@ function resolveIosEnterpriseProvisioning(
|
|||||||
): IosEnterpriseProvisioning | undefined {
|
): IosEnterpriseProvisioning | undefined {
|
||||||
return ctx.buildProfile.enterpriseProvisioning;
|
return ctx.buildProfile.enterpriseProvisioning;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getFormattedCommitMessageAsync(
|
||||||
|
vcsClient: Client
|
||||||
|
): Promise<string | undefined> {
|
||||||
|
const maybeCommitMessage = (await vcsClient.getLastCommitMessageAsync())?.trim();
|
||||||
|
if (!maybeCommitMessage) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const lines = maybeCommitMessage.split('\n');
|
||||||
|
const withoutEmptyLines = lines.filter(i => i);
|
||||||
|
const message = withoutEmptyLines.join(' ');
|
||||||
|
return message.length > 1024 ? message.substring(0, 1021) + '...' : message;
|
||||||
|
}
|
||||||
@@ -1,9 +1,15 @@
|
|||||||
import { Platform, Workflow } from '@expo/eas-build-job';
|
import { Platform, Workflow } from '@expo/eas-build-job';
|
||||||
import { BuildProfile, SubmitProfile } from '@expo/eas-json';
|
import { BuildProfile, EasJson, EasJsonReader, SubmitProfile } from '@expo/eas-json';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import nullthrows from 'nullthrows';
|
import nullthrows from 'nullthrows';
|
||||||
|
|
||||||
import { AppPlatform, BuildFragment, BuildStatus, SubmissionFragment } from '../graphql/generated';
|
import {
|
||||||
|
AppPlatform,
|
||||||
|
BuildFragment,
|
||||||
|
BuildResourceClass,
|
||||||
|
BuildStatus,
|
||||||
|
SubmissionFragment,
|
||||||
|
} from '../graphql/generated';
|
||||||
import { toAppPlatform, toPlatform } from '../graphql/types/AppPlatform';
|
import { toAppPlatform, toPlatform } from '../graphql/types/AppPlatform';
|
||||||
import Log from '../log';
|
import Log from '../log';
|
||||||
import {
|
import {
|
||||||
@@ -30,6 +36,7 @@ import { BuildContext } from './context';
|
|||||||
import { createBuildContextAsync } from './createContext';
|
import { createBuildContextAsync } from './createContext';
|
||||||
import { prepareIosBuildAsync } from './ios/build';
|
import { prepareIosBuildAsync } from './ios/build';
|
||||||
import { LocalBuildOptions } from './local';
|
import { LocalBuildOptions } from './local';
|
||||||
|
import { UserInputResourceClass } from './types';
|
||||||
import { ensureExpoDevClientInstalledForDevClientBuildsAsync } from './utils/devClient';
|
import { ensureExpoDevClientInstalledForDevClientBuildsAsync } from './utils/devClient';
|
||||||
import { printBuildResults, printLogsUrls } from './utils/printBuildInfo';
|
import { printBuildResults, printLogsUrls } from './utils/printBuildInfo';
|
||||||
import { ensureRepoIsCleanAsync } from './utils/repository';
|
import { ensureRepoIsCleanAsync } from './utils/repository';
|
||||||
@@ -47,8 +54,24 @@ export interface BuildFlags {
|
|||||||
autoSubmit: boolean;
|
autoSubmit: boolean;
|
||||||
submitProfile?: string;
|
submitProfile?: string;
|
||||||
localBuildOptions: LocalBuildOptions;
|
localBuildOptions: LocalBuildOptions;
|
||||||
|
userInputResourceClass?: UserInputResourceClass;
|
||||||
|
message?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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> {
|
export async function runBuildAndSubmitAsync(projectDir: string, flags: BuildFlags): Promise<void> {
|
||||||
await getVcsClient().ensureRepoExistsAsync();
|
await getVcsClient().ensureRepoExistsAsync();
|
||||||
await ensureRepoIsCleanAsync(flags.nonInteractive);
|
await ensureRepoIsCleanAsync(flags.nonInteractive);
|
||||||
@@ -57,11 +80,13 @@ export async function runBuildAndSubmitAsync(projectDir: string, flags: BuildFla
|
|||||||
projectDir,
|
projectDir,
|
||||||
nonInteractive: flags.nonInteractive,
|
nonInteractive: flags.nonInteractive,
|
||||||
});
|
});
|
||||||
|
const easJsonReader = new EasJsonReader(projectDir);
|
||||||
|
const easJsonCliConfig: EasJson['cli'] = (await easJsonReader.getCliConfigAsync()) ?? {};
|
||||||
|
|
||||||
const platforms = toPlatforms(flags.requestedPlatform);
|
const platforms = toPlatforms(flags.requestedPlatform);
|
||||||
const buildProfiles = await getProfilesAsync({
|
const buildProfiles = await getProfilesAsync({
|
||||||
type: 'build',
|
type: 'build',
|
||||||
projectDir,
|
easJsonReader,
|
||||||
platforms,
|
platforms,
|
||||||
profileName: flags.profile ?? undefined,
|
profileName: flags.profile ?? undefined,
|
||||||
});
|
});
|
||||||
@@ -84,6 +109,11 @@ export async function runBuildAndSubmitAsync(projectDir: string, flags: BuildFla
|
|||||||
flags,
|
flags,
|
||||||
moreBuilds: platforms.length > 1,
|
moreBuilds: platforms.length > 1,
|
||||||
buildProfile,
|
buildProfile,
|
||||||
|
resourceClass:
|
||||||
|
platformToGraphQLResourceClassMapping[buildProfile.platform][
|
||||||
|
flags.userInputResourceClass ?? UserInputResourceClass.DEFAULT
|
||||||
|
],
|
||||||
|
easJsonCliConfig,
|
||||||
});
|
});
|
||||||
if (maybeBuild) {
|
if (maybeBuild) {
|
||||||
startedBuilds.push({ build: maybeBuild, buildProfile });
|
startedBuilds.push({ build: maybeBuild, buildProfile });
|
||||||
@@ -102,7 +132,7 @@ export async function runBuildAndSubmitAsync(projectDir: string, flags: BuildFla
|
|||||||
const submissions: SubmissionFragment[] = [];
|
const submissions: SubmissionFragment[] = [];
|
||||||
if (flags.autoSubmit) {
|
if (flags.autoSubmit) {
|
||||||
const submitProfiles = await getProfilesAsync({
|
const submitProfiles = await getProfilesAsync({
|
||||||
projectDir,
|
easJsonReader,
|
||||||
platforms,
|
platforms,
|
||||||
profileName: flags.submitProfile,
|
profileName: flags.submitProfile,
|
||||||
type: 'submit',
|
type: 'submit',
|
||||||
@@ -160,20 +190,27 @@ async function prepareAndStartBuildAsync({
|
|||||||
flags,
|
flags,
|
||||||
moreBuilds,
|
moreBuilds,
|
||||||
buildProfile,
|
buildProfile,
|
||||||
|
resourceClass,
|
||||||
|
easJsonCliConfig,
|
||||||
}: {
|
}: {
|
||||||
projectDir: string;
|
projectDir: string;
|
||||||
flags: BuildFlags;
|
flags: BuildFlags;
|
||||||
moreBuilds: boolean;
|
moreBuilds: boolean;
|
||||||
buildProfile: ProfileData<'build'>;
|
buildProfile: ProfileData<'build'>;
|
||||||
|
resourceClass: BuildResourceClass;
|
||||||
|
easJsonCliConfig: EasJson['cli'];
|
||||||
}): Promise<{ build: BuildFragment | undefined; buildCtx: BuildContext<Platform> }> {
|
}): Promise<{ build: BuildFragment | undefined; buildCtx: BuildContext<Platform> }> {
|
||||||
const buildCtx = await createBuildContextAsync({
|
const buildCtx = await createBuildContextAsync({
|
||||||
buildProfileName: buildProfile.profileName,
|
buildProfileName: buildProfile.profileName,
|
||||||
|
resourceClass,
|
||||||
clearCache: flags.clearCache,
|
clearCache: flags.clearCache,
|
||||||
buildProfile: buildProfile.profile,
|
buildProfile: buildProfile.profile,
|
||||||
nonInteractive: flags.nonInteractive,
|
nonInteractive: flags.nonInteractive,
|
||||||
platform: buildProfile.platform,
|
platform: buildProfile.platform,
|
||||||
projectDir,
|
projectDir,
|
||||||
localBuildOptions: flags.localBuildOptions,
|
localBuildOptions: flags.localBuildOptions,
|
||||||
|
easJsonCliConfig,
|
||||||
|
message: flags.message,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (moreBuilds) {
|
if (moreBuilds) {
|
||||||
|
|||||||
@@ -12,3 +12,8 @@ export enum BuildDistributionType {
|
|||||||
INTERNAL = 'internal',
|
INTERNAL = 'internal',
|
||||||
SIMULATOR = 'simulator',
|
SIMULATOR = 'simulator',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum UserInputResourceClass {
|
||||||
|
DEFAULT = 'default',
|
||||||
|
LARGE = 'large',
|
||||||
|
}
|
||||||
@@ -35,3 +35,16 @@ export function getInternalDistributionInstallUrl(build: BuildFragment): string
|
|||||||
|
|
||||||
return build.artifacts.buildUrl;
|
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();
|
||||||
|
}
|
||||||
@@ -107,7 +107,7 @@ describe(EasCommand.name, () => {
|
|||||||
await TestEasCommand.run().then(() => {
|
await TestEasCommand.run().then(() => {
|
||||||
throw new Error('foo');
|
throw new Error('foo');
|
||||||
});
|
});
|
||||||
} catch (error) {}
|
} catch {}
|
||||||
|
|
||||||
expect(flushAsync).toHaveBeenCalled();
|
expect(flushAsync).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
@@ -11,6 +10,7 @@ import {
|
|||||||
UpdateBranch,
|
UpdateBranch,
|
||||||
} from '../../graphql/generated';
|
} from '../../graphql/generated';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import {
|
import {
|
||||||
findProjectRootAsync,
|
findProjectRootAsync,
|
||||||
getProjectFullNameAsync,
|
getProjectFullNameAsync,
|
||||||
@@ -79,7 +79,7 @@ export default class BranchCreate extends EasCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const fullName = await getProjectFullNameAsync(exp);
|
const fullName = await getProjectFullNameAsync(exp);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
@@ -13,6 +12,7 @@ import {
|
|||||||
GetBranchInfoQueryVariables,
|
GetBranchInfoQueryVariables,
|
||||||
} from '../../graphql/generated';
|
} from '../../graphql/generated';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import {
|
import {
|
||||||
findProjectRootAsync,
|
findProjectRootAsync,
|
||||||
getProjectFullNameAsync,
|
getProjectFullNameAsync,
|
||||||
@@ -103,7 +103,7 @@ export default class BranchDelete extends EasCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const fullName = await getProjectFullNameAsync(exp);
|
const fullName = await getProjectFullNameAsync(exp);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import CliTable from 'cli-table3';
|
import CliTable from 'cli-table3';
|
||||||
@@ -14,6 +13,7 @@ import {
|
|||||||
} from '../../graphql/generated';
|
} from '../../graphql/generated';
|
||||||
import { UpdateBranchFragmentNode } from '../../graphql/types/UpdateBranch';
|
import { UpdateBranchFragmentNode } from '../../graphql/types/UpdateBranch';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
||||||
import { UPDATE_COLUMNS, formatUpdate, getPlatformsForGroup } from '../../update/utils';
|
import { UPDATE_COLUMNS, formatUpdate, getPlatformsForGroup } from '../../update/utils';
|
||||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||||
@@ -71,7 +71,7 @@ export default class BranchList extends EasCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
const branches = await listBranchesAsync({ projectId });
|
const branches = await listBranchesAsync({ projectId });
|
||||||
if (flags.json) {
|
if (flags.json) {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
@@ -12,6 +11,7 @@ import {
|
|||||||
UpdateBranch,
|
UpdateBranch,
|
||||||
} from '../../graphql/generated';
|
} from '../../graphql/generated';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import {
|
import {
|
||||||
findProjectRootAsync,
|
findProjectRootAsync,
|
||||||
getProjectFullNameAsync,
|
getProjectFullNameAsync,
|
||||||
@@ -78,7 +78,7 @@ export default class BranchRename extends EasCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const fullName = await getProjectFullNameAsync(exp);
|
const fullName = await getProjectFullNameAsync(exp);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import Table from 'cli-table3';
|
import Table from 'cli-table3';
|
||||||
@@ -6,6 +5,7 @@ import Table from 'cli-table3';
|
|||||||
import EasCommand from '../../commandUtils/EasCommand';
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
import { UpdateQuery } from '../../graphql/queries/UpdateQuery';
|
import { UpdateQuery } from '../../graphql/queries/UpdateQuery';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
||||||
import { promptAsync } from '../../prompts';
|
import { promptAsync } from '../../prompts';
|
||||||
import { UPDATE_COLUMNS, formatUpdate, getPlatformsForGroup } from '../../update/utils';
|
import { UPDATE_COLUMNS, formatUpdate, getPlatformsForGroup } from '../../update/utils';
|
||||||
@@ -41,7 +41,7 @@ export default class BranchView extends EasCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
|
|
||||||
if (!name) {
|
if (!name) {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
|
|
||||||
@@ -14,6 +13,7 @@ import { BuildQuery } from '../../graphql/queries/BuildQuery';
|
|||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
import { ora } from '../../ora';
|
import { ora } from '../../ora';
|
||||||
import { appPlatformEmojis } from '../../platform';
|
import { appPlatformEmojis } from '../../platform';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import {
|
import {
|
||||||
findProjectRootAsync,
|
findProjectRootAsync,
|
||||||
getProjectFullNameAsync,
|
getProjectFullNameAsync,
|
||||||
@@ -104,7 +104,7 @@ async function selectBuildToCancelAsync(
|
|||||||
async function ensureBuildExistsAsync(buildId: string): Promise<void> {
|
async function ensureBuildExistsAsync(buildId: string): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await BuildQuery.byIdAsync(buildId);
|
await BuildQuery.byIdAsync(buildId);
|
||||||
} catch (err) {
|
} catch {
|
||||||
throw new Error(`Couldn't find a build matching the id ${buildId}`);
|
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 { BUILD_ID: buildIdFromArg } = (await this.parse(BuildCancel)).args;
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
const projectFullName = await getProjectFullNameAsync(exp);
|
const projectFullName = await getProjectFullNameAsync(exp);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Platform, Workflow } from '@expo/eas-build-job';
|
import { Platform, Workflow } from '@expo/eas-build-job';
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
@@ -8,6 +7,7 @@ import { ensureProjectConfiguredAsync } from '../../build/configure';
|
|||||||
import EasCommand from '../../commandUtils/EasCommand';
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
import Log, { learnMore } from '../../log';
|
import Log, { learnMore } from '../../log';
|
||||||
import { RequestedPlatform } from '../../platform';
|
import { RequestedPlatform } from '../../platform';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import { findProjectRootAsync, isExpoUpdatesInstalled } from '../../project/projectUtils';
|
import { findProjectRootAsync, isExpoUpdatesInstalled } from '../../project/projectUtils';
|
||||||
import { resolveWorkflowAsync } from '../../project/workflow';
|
import { resolveWorkflowAsync } from '../../project/workflow';
|
||||||
import { promptAsync } from '../../prompts';
|
import { promptAsync } from '../../prompts';
|
||||||
@@ -55,7 +55,7 @@ export default class BuildConfigure extends EasCommand {
|
|||||||
|
|
||||||
// configure expo-updates
|
// configure expo-updates
|
||||||
if (expoUpdatesIsInstalled) {
|
if (expoUpdatesIsInstalled) {
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
|
|
||||||
if ([RequestedPlatform.Android, RequestedPlatform.All].includes(platform)) {
|
if ([RequestedPlatform.Android, RequestedPlatform.All].includes(platform)) {
|
||||||
const workflow = await resolveWorkflowAsync(projectDir, Platform.ANDROID);
|
const workflow = await resolveWorkflowAsync(projectDir, Platform.ANDROID);
|
||||||
|
|||||||
@@ -1,21 +1,13 @@
|
|||||||
import { EasJsonReader } from '@expo/eas-json';
|
|
||||||
import { Errors, Flags } from '@oclif/core';
|
import { Errors, Flags } from '@oclif/core';
|
||||||
import chalk from 'chalk';
|
|
||||||
import figures from 'figures';
|
|
||||||
import fs from 'fs-extra';
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
import { BuildFlags, runBuildAndSubmitAsync } from '../../build/runBuildAndSubmit';
|
import { BuildFlags, runBuildAndSubmitAsync } from '../../build/runBuildAndSubmit';
|
||||||
import { ensureRepoIsCleanAsync, reviewAndCommitChangesAsync } from '../../build/utils/repository';
|
import { UserInputResourceClass } from '../../build/types';
|
||||||
import EasCommand from '../../commandUtils/EasCommand';
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
import Log, { learnMore, link } from '../../log';
|
import Log from '../../log';
|
||||||
import { RequestedPlatform, selectRequestedPlatformAsync } from '../../platform';
|
import { RequestedPlatform, selectRequestedPlatformAsync } from '../../platform';
|
||||||
import { findProjectRootAsync } from '../../project/projectUtils';
|
import { findProjectRootAsync } from '../../project/projectUtils';
|
||||||
import { selectAsync } from '../../prompts';
|
|
||||||
import { easCliVersion } from '../../utils/easCli';
|
|
||||||
import { enableJsonOutput } from '../../utils/json';
|
import { enableJsonOutput } from '../../utils/json';
|
||||||
import { getVcsClient, setVcsClient } from '../../vcs';
|
|
||||||
import GitClient from '../../vcs/clients/git';
|
|
||||||
|
|
||||||
interface RawBuildFlags {
|
interface RawBuildFlags {
|
||||||
platform?: string;
|
platform?: string;
|
||||||
@@ -30,6 +22,8 @@ interface RawBuildFlags {
|
|||||||
json: boolean;
|
json: boolean;
|
||||||
'auto-submit': boolean;
|
'auto-submit': boolean;
|
||||||
'auto-submit-with-profile'?: string;
|
'auto-submit-with-profile'?: string;
|
||||||
|
'resource-class'?: UserInputResourceClass;
|
||||||
|
message?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Build extends EasCommand {
|
export default class Build extends EasCommand {
|
||||||
@@ -88,6 +82,15 @@ export default class Build extends EasCommand {
|
|||||||
helpValue: 'PROFILE_NAME',
|
helpValue: 'PROFILE_NAME',
|
||||||
exclusive: ['auto-submit'],
|
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]',
|
||||||
|
}),
|
||||||
|
message: Flags.string({
|
||||||
|
char: 'm',
|
||||||
|
description: 'A short message describing the build',
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
async runAsync(): Promise<void> {
|
async runAsync(): Promise<void> {
|
||||||
@@ -98,7 +101,6 @@ export default class Build extends EasCommand {
|
|||||||
const flags = await this.sanitizeFlagsAsync(rawFlags);
|
const flags = await this.sanitizeFlagsAsync(rawFlags);
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
await handleDeprecatedEasJsonAsync(projectDir, flags.nonInteractive);
|
|
||||||
|
|
||||||
await runBuildAndSubmitAsync(projectDir, flags);
|
await runBuildAndSubmitAsync(projectDir, flags);
|
||||||
}
|
}
|
||||||
@@ -146,6 +148,11 @@ export default class Build extends EasCommand {
|
|||||||
Log.newLine();
|
Log.newLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const message = flags['message'];
|
||||||
|
if (message && message.length > 1024) {
|
||||||
|
Errors.error('Message cannot be longer than 1024 characters.', { exit: 1 });
|
||||||
|
}
|
||||||
|
|
||||||
const profile = flags['profile'];
|
const profile = flags['profile'];
|
||||||
return {
|
return {
|
||||||
requestedPlatform,
|
requestedPlatform,
|
||||||
@@ -165,70 +172,8 @@ export default class Build extends EasCommand {
|
|||||||
json: flags['json'],
|
json: flags['json'],
|
||||||
autoSubmit: flags['auto-submit'] || flags['auto-submit-with-profile'] !== undefined,
|
autoSubmit: flags['auto-submit'] || flags['auto-submit-with-profile'] !== undefined,
|
||||||
submitProfile: flags['auto-submit-with-profile'] ?? profile,
|
submitProfile: flags['auto-submit-with-profile'] ?? profile,
|
||||||
|
userInputResourceClass: flags['resource-class'] ?? UserInputResourceClass.DEFAULT,
|
||||||
|
message,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -102,7 +102,7 @@ export default class BuildInspect extends EasCommand {
|
|||||||
if (!flags.verbose) {
|
if (!flags.verbose) {
|
||||||
Log.log(chalk.green('Build successful'));
|
Log.log(chalk.green('Build successful'));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch {
|
||||||
if (!flags.verbose) {
|
if (!flags.verbose) {
|
||||||
Log.error('Build failed');
|
Log.error('Build failed');
|
||||||
Log.error(`Re-run this command with ${chalk.bold('--verbose')} flag to see the logs`);
|
Log.error(`Re-run this command with ${chalk.bold('--verbose')} flag to see the logs`);
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
|
|
||||||
@@ -14,6 +13,7 @@ import { BuildQuery } from '../../graphql/queries/BuildQuery';
|
|||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
import { ora } from '../../ora';
|
import { ora } from '../../ora';
|
||||||
import { RequestedPlatform } from '../../platform';
|
import { RequestedPlatform } from '../../platform';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import {
|
import {
|
||||||
findProjectRootAsync,
|
findProjectRootAsync,
|
||||||
getProjectFullNameAsync,
|
getProjectFullNameAsync,
|
||||||
@@ -77,7 +77,7 @@ export default class BuildList extends EasCommand {
|
|||||||
const graphqlBuildDistribution = toGraphQLBuildDistribution(buildDistribution);
|
const graphqlBuildDistribution = toGraphQLBuildDistribution(buildDistribution);
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
const projectName = await getProjectFullNameAsync(exp);
|
const projectName = await getProjectFullNameAsync(exp);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
import { getRuntimeVersionNullable } from '@expo/config-plugins/build/utils/Updates';
|
||||||
|
import { Platform } from '@expo/eas-build-job';
|
||||||
|
import { EasJsonReader } from '@expo/eas-json';
|
||||||
|
import { Flags } from '@oclif/core';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
|
||||||
|
import EasCommand from '../../../commandUtils/EasCommand';
|
||||||
|
import { AppVersionMutation } from '../../../graphql/mutations/AppVersionMutation';
|
||||||
|
import { AppVersionQuery } from '../../../graphql/queries/AppVersionQuery';
|
||||||
|
import { toAppPlatform } from '../../../graphql/types/AppPlatform';
|
||||||
|
import Log from '../../../log';
|
||||||
|
import { selectPlatformAsync } from '../../../platform';
|
||||||
|
import { VERSION_CODE_REQUIREMENTS, isValidVersionCode } from '../../../project/android/versions';
|
||||||
|
import { getApplicationIdentifierAsync } from '../../../project/applicationIdentifier';
|
||||||
|
import { getExpoConfig } from '../../../project/expoConfig';
|
||||||
|
import { BUILD_NUMBER_REQUIREMENTS, isValidBuildNumber } from '../../../project/ios/versions';
|
||||||
|
import {
|
||||||
|
findProjectRootAsync,
|
||||||
|
getProjectFullNameAsync,
|
||||||
|
getProjectIdAsync,
|
||||||
|
} from '../../../project/projectUtils';
|
||||||
|
import {
|
||||||
|
ensureRemoteVersionPolicyAsync,
|
||||||
|
getBuildVersionName,
|
||||||
|
validateAppConfigForRemoteVersionPolicyAsync,
|
||||||
|
} from '../../../project/remoteVersionSource';
|
||||||
|
import { promptAsync } from '../../../prompts';
|
||||||
|
|
||||||
|
export default class BuildVersionSetView extends EasCommand {
|
||||||
|
static description = 'Update version of an app.';
|
||||||
|
static hidden = true;
|
||||||
|
|
||||||
|
static flags = {
|
||||||
|
platform: Flags.enum({
|
||||||
|
char: 'p',
|
||||||
|
options: ['android', 'ios'],
|
||||||
|
}),
|
||||||
|
profile: Flags.string({
|
||||||
|
description:
|
||||||
|
'Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.',
|
||||||
|
helpValue: 'PROFILE_NAME',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
public async runAsync(): Promise<void> {
|
||||||
|
const { flags } = await this.parse(BuildVersionSetView);
|
||||||
|
|
||||||
|
const projectDir = await findProjectRootAsync();
|
||||||
|
|
||||||
|
const platform = await selectPlatformAsync(flags.platform);
|
||||||
|
const easJsonReader = new EasJsonReader(projectDir);
|
||||||
|
await ensureRemoteVersionPolicyAsync(projectDir, easJsonReader);
|
||||||
|
const profile = await easJsonReader.getBuildProfileAsync(platform, flags.profile ?? undefined);
|
||||||
|
|
||||||
|
const exp = getExpoConfig(projectDir, { env: profile.env });
|
||||||
|
const projectId = await getProjectIdAsync(exp);
|
||||||
|
const projectFullName = await getProjectFullNameAsync(exp);
|
||||||
|
await validateAppConfigForRemoteVersionPolicyAsync(exp);
|
||||||
|
|
||||||
|
const applicationIdentifier = await getApplicationIdentifierAsync(
|
||||||
|
projectDir,
|
||||||
|
exp,
|
||||||
|
profile,
|
||||||
|
platform
|
||||||
|
);
|
||||||
|
const remoteVersions = await AppVersionQuery.latestVersionAsync(
|
||||||
|
projectId,
|
||||||
|
toAppPlatform(platform),
|
||||||
|
applicationIdentifier
|
||||||
|
);
|
||||||
|
const currentStateMessage = remoteVersions?.buildVersion
|
||||||
|
? `Project ${chalk.bold(projectFullName)} with ${getApplicationIdentifierName(
|
||||||
|
platform
|
||||||
|
)} "${applicationIdentifier}" is configured with ${getBuildVersionName(platform)} ${
|
||||||
|
remoteVersions.buildVersion
|
||||||
|
}.`
|
||||||
|
: `Project ${chalk.bold(projectFullName)} with ${getApplicationIdentifierName(
|
||||||
|
platform
|
||||||
|
)} "${applicationIdentifier}" does not have any ${getBuildVersionName(
|
||||||
|
platform
|
||||||
|
)} configured.`;
|
||||||
|
|
||||||
|
const versionPromptMessage = remoteVersions?.buildVersion
|
||||||
|
? `What version would you like to set?`
|
||||||
|
: `What version would you like to initialize it with?`;
|
||||||
|
Log.log(currentStateMessage);
|
||||||
|
|
||||||
|
const { version } = await promptAsync({
|
||||||
|
type: platform === Platform.ANDROID ? 'number' : 'text',
|
||||||
|
name: 'version',
|
||||||
|
message: versionPromptMessage,
|
||||||
|
validate:
|
||||||
|
platform === Platform.ANDROID
|
||||||
|
? value => isValidVersionCode(value) || `Invalid value: ${VERSION_CODE_REQUIREMENTS}.`
|
||||||
|
: value => isValidBuildNumber(value) || `Invalid value: ${BUILD_NUMBER_REQUIREMENTS}.`,
|
||||||
|
});
|
||||||
|
await AppVersionMutation.createAppVersionAsync({
|
||||||
|
appId: projectId,
|
||||||
|
platform: toAppPlatform(platform),
|
||||||
|
applicationIdentifier,
|
||||||
|
storeVersion: exp.version ?? '1.0.0',
|
||||||
|
buildVersion: String(version),
|
||||||
|
runtimeVersion: getRuntimeVersionNullable(exp, platform) ?? undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getApplicationIdentifierName(platform: Platform): string {
|
||||||
|
if (platform === Platform.ANDROID) {
|
||||||
|
return 'application ID';
|
||||||
|
} else {
|
||||||
|
return 'bundle identifier';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,184 @@
|
|||||||
|
import { ExpoConfig } from '@expo/config';
|
||||||
|
import { Platform, Workflow } from '@expo/eas-build-job';
|
||||||
|
import { BuildProfile, EasJsonReader } from '@expo/eas-json';
|
||||||
|
import { Flags } from '@oclif/core';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
|
||||||
|
import { updateNativeVersionsAsync as updateAndroidNativeVersionsAsync } from '../../../build/android/version';
|
||||||
|
import { updateNativeVersionsAsync as updateIosNativeVersionsAsync } from '../../../build/ios/version';
|
||||||
|
import EasCommand from '../../../commandUtils/EasCommand';
|
||||||
|
import { AppVersionQuery } from '../../../graphql/queries/AppVersionQuery';
|
||||||
|
import { toAppPlatform } from '../../../graphql/types/AppPlatform';
|
||||||
|
import Log from '../../../log';
|
||||||
|
import {
|
||||||
|
appPlatformDisplayNames,
|
||||||
|
selectRequestedPlatformAsync,
|
||||||
|
toPlatforms,
|
||||||
|
} from '../../../platform';
|
||||||
|
import { getAppBuildGradleAsync } from '../../../project/android/gradleUtils';
|
||||||
|
import { VERSION_CODE_REQUIREMENTS, isValidVersionCode } from '../../../project/android/versions';
|
||||||
|
import { getApplicationIdentifierAsync } from '../../../project/applicationIdentifier';
|
||||||
|
import { getExpoConfig } from '../../../project/expoConfig';
|
||||||
|
import { resolveXcodeBuildContextAsync } from '../../../project/ios/scheme';
|
||||||
|
import { resolveTargetsAsync } from '../../../project/ios/target';
|
||||||
|
import { BUILD_NUMBER_REQUIREMENTS, isValidBuildNumber } from '../../../project/ios/versions';
|
||||||
|
import { findProjectRootAsync, getProjectIdAsync } from '../../../project/projectUtils';
|
||||||
|
import {
|
||||||
|
ensureRemoteVersionPolicyAsync,
|
||||||
|
getBuildVersionName,
|
||||||
|
validateAppConfigForRemoteVersionPolicyAsync,
|
||||||
|
} from '../../../project/remoteVersionSource';
|
||||||
|
import { resolveWorkflowAsync } from '../../../project/workflow';
|
||||||
|
import { getProfilesAsync } from '../../../utils/profiles';
|
||||||
|
|
||||||
|
interface SyncContext<T extends Platform> {
|
||||||
|
projectDir: string;
|
||||||
|
exp: ExpoConfig;
|
||||||
|
workflow: Workflow;
|
||||||
|
profile: BuildProfile<T>;
|
||||||
|
buildVersion: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class BuildVersionSyncView extends EasCommand {
|
||||||
|
public static description = 'Update a version in native code with a value stored on EAS servers';
|
||||||
|
static hidden = true;
|
||||||
|
|
||||||
|
public static flags = {
|
||||||
|
platform: Flags.enum({
|
||||||
|
char: 'p',
|
||||||
|
options: ['android', 'ios', 'all'],
|
||||||
|
}),
|
||||||
|
profile: Flags.string({
|
||||||
|
description:
|
||||||
|
'Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.',
|
||||||
|
helpValue: 'PROFILE_NAME',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
public async runAsync(): Promise<void> {
|
||||||
|
const { flags } = await this.parse(BuildVersionSyncView);
|
||||||
|
const projectDir = await findProjectRootAsync();
|
||||||
|
|
||||||
|
const requestedPlatform = await selectRequestedPlatformAsync(flags.platform);
|
||||||
|
const easJsonReader = new EasJsonReader(projectDir);
|
||||||
|
await ensureRemoteVersionPolicyAsync(projectDir, easJsonReader);
|
||||||
|
|
||||||
|
const platforms = toPlatforms(requestedPlatform);
|
||||||
|
const buildProfiles = await getProfilesAsync({
|
||||||
|
type: 'build',
|
||||||
|
easJsonReader,
|
||||||
|
platforms,
|
||||||
|
profileName: flags.profile ?? undefined,
|
||||||
|
});
|
||||||
|
for (const profileInfo of buildProfiles) {
|
||||||
|
const exp = getExpoConfig(projectDir, { env: profileInfo.profile.env });
|
||||||
|
const projectId = await getProjectIdAsync(exp);
|
||||||
|
await validateAppConfigForRemoteVersionPolicyAsync(exp);
|
||||||
|
const platformDisplayName = appPlatformDisplayNames[toAppPlatform(profileInfo.platform)];
|
||||||
|
|
||||||
|
const applicationIdentifier = await getApplicationIdentifierAsync(
|
||||||
|
projectDir,
|
||||||
|
exp,
|
||||||
|
profileInfo.profile,
|
||||||
|
profileInfo.platform
|
||||||
|
);
|
||||||
|
const remoteVersions = await AppVersionQuery.latestVersionAsync(
|
||||||
|
projectId,
|
||||||
|
toAppPlatform(profileInfo.platform),
|
||||||
|
applicationIdentifier
|
||||||
|
);
|
||||||
|
const workflow = await resolveWorkflowAsync(projectDir, profileInfo.platform);
|
||||||
|
if (!remoteVersions?.buildVersion) {
|
||||||
|
Log.warn(
|
||||||
|
`Skipping versions sync for ${platformDisplayName}. There are no versions configured on Expo servers, use "eas build:version:set" or run a build to initialize it.`
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (workflow === Workflow.MANAGED) {
|
||||||
|
Log.warn(
|
||||||
|
`The remote value for the ${platformDisplayName} ${getBuildVersionName(
|
||||||
|
profileInfo.platform
|
||||||
|
)} is ${chalk.bold(
|
||||||
|
remoteVersions?.buildVersion
|
||||||
|
)}, but it was not synced to the local project. This command has no effect on projects using managed workflow.`
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (profileInfo.platform === Platform.ANDROID) {
|
||||||
|
this.syncAndroidAsync({
|
||||||
|
projectDir,
|
||||||
|
exp,
|
||||||
|
profile: profileInfo.profile as BuildProfile<Platform.ANDROID>,
|
||||||
|
workflow,
|
||||||
|
buildVersion: remoteVersions.buildVersion,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.syncIosAsync({
|
||||||
|
projectDir,
|
||||||
|
exp,
|
||||||
|
profile: profileInfo.profile as BuildProfile<Platform.IOS>,
|
||||||
|
workflow,
|
||||||
|
buildVersion: remoteVersions.buildVersion,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Log.withTick(
|
||||||
|
`Successfully updated the ${platformDisplayName} ${getBuildVersionName(
|
||||||
|
profileInfo.platform
|
||||||
|
)} in native code to ${chalk.bold(remoteVersions?.buildVersion)}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async syncIosAsync({
|
||||||
|
workflow,
|
||||||
|
projectDir,
|
||||||
|
exp,
|
||||||
|
profile,
|
||||||
|
buildVersion,
|
||||||
|
}: SyncContext<Platform.IOS>): Promise<void> {
|
||||||
|
const xcodeBuildContext = await resolveXcodeBuildContextAsync(
|
||||||
|
{ exp, projectDir, nonInteractive: false },
|
||||||
|
profile
|
||||||
|
);
|
||||||
|
const targets = await resolveTargetsAsync({
|
||||||
|
projectDir,
|
||||||
|
exp,
|
||||||
|
xcodeBuildContext,
|
||||||
|
env: profile.env,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!isValidBuildNumber(buildVersion)) {
|
||||||
|
throw new Error(`Invalid buildNumber (${buildVersion}), ${BUILD_NUMBER_REQUIREMENTS}.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (workflow === Workflow.GENERIC) {
|
||||||
|
await updateIosNativeVersionsAsync({
|
||||||
|
projectDir,
|
||||||
|
buildNumber: buildVersion,
|
||||||
|
targets,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async syncAndroidAsync({
|
||||||
|
projectDir,
|
||||||
|
workflow,
|
||||||
|
buildVersion,
|
||||||
|
}: SyncContext<Platform.ANDROID>): Promise<void> {
|
||||||
|
if (!isValidVersionCode(buildVersion)) {
|
||||||
|
throw new Error(`Invalid versionCode (${buildVersion}), ${VERSION_CODE_REQUIREMENTS}.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (workflow === Workflow.GENERIC) {
|
||||||
|
const buildGradle = await getAppBuildGradleAsync(projectDir);
|
||||||
|
const isMultiFlavor =
|
||||||
|
buildGradle.android?.productFlavors || buildGradle.android?.flavorDimensions;
|
||||||
|
if (isMultiFlavor) {
|
||||||
|
throw new Error(
|
||||||
|
"Versions in native code can't be automatically synced in multi-flavor Android projects. If you are using EAS Build with app version source set to remote, the correct values will be injected at the build time."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await updateAndroidNativeVersionsAsync({ projectDir, versionCode: Number(buildVersion) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
|
|
||||||
import { formatGraphQLBuild } from '../../build/utils/formatBuild';
|
import { formatGraphQLBuild } from '../../build/utils/formatBuild';
|
||||||
@@ -7,6 +6,7 @@ import { BuildFragment } from '../../graphql/generated';
|
|||||||
import { BuildQuery } from '../../graphql/queries/BuildQuery';
|
import { BuildQuery } from '../../graphql/queries/BuildQuery';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
import { ora } from '../../ora';
|
import { ora } from '../../ora';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import {
|
import {
|
||||||
findProjectRootAsync,
|
findProjectRootAsync,
|
||||||
getProjectFullNameAsync,
|
getProjectFullNameAsync,
|
||||||
@@ -35,7 +35,7 @@ export default class BuildView extends EasCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
const projectName = await getProjectFullNameAsync(exp);
|
const projectName = await getProjectFullNameAsync(exp);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
@@ -11,6 +10,7 @@ import {
|
|||||||
} from '../../graphql/generated';
|
} from '../../graphql/generated';
|
||||||
import { BranchQuery } from '../../graphql/queries/BranchQuery';
|
import { BranchQuery } from '../../graphql/queries/BranchQuery';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import {
|
import {
|
||||||
findProjectRootAsync,
|
findProjectRootAsync,
|
||||||
getProjectFullNameAsync,
|
getProjectFullNameAsync,
|
||||||
@@ -88,7 +88,7 @@ export default class ChannelCreate extends EasCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
|
|
||||||
if (!channelName) {
|
if (!channelName) {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
|
|
||||||
@@ -12,6 +11,7 @@ import {
|
|||||||
GetChannelInfoQueryVariables,
|
GetChannelInfoQueryVariables,
|
||||||
} from '../../graphql/generated';
|
} from '../../graphql/generated';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import {
|
import {
|
||||||
findProjectRootAsync,
|
findProjectRootAsync,
|
||||||
getProjectFullNameAsync,
|
getProjectFullNameAsync,
|
||||||
@@ -55,7 +55,7 @@ export default class ChannelDelete extends EasCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const fullName = await getProjectFullNameAsync(exp);
|
const fullName = await getProjectFullNameAsync(exp);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
@@ -15,6 +14,7 @@ import {
|
|||||||
} from '../../graphql/generated';
|
} from '../../graphql/generated';
|
||||||
import { BranchQuery } from '../../graphql/queries/BranchQuery';
|
import { BranchQuery } from '../../graphql/queries/BranchQuery';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
||||||
import { promptAsync } from '../../prompts';
|
import { promptAsync } from '../../prompts';
|
||||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||||
@@ -120,7 +120,7 @@ export default class ChannelEdit extends EasCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
|
|
||||||
const channelName = args.name ?? (await promptForChannelAsync());
|
const channelName = args.name ?? (await promptForChannelAsync());
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
|
|
||||||
@@ -9,6 +8,7 @@ import {
|
|||||||
GetAllChannelsForAppQueryVariables,
|
GetAllChannelsForAppQueryVariables,
|
||||||
} from '../../graphql/generated';
|
} from '../../graphql/generated';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
||||||
import formatFields from '../../utils/formatFields';
|
import formatFields from '../../utils/formatFields';
|
||||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||||
@@ -85,7 +85,7 @@ export default class ChannelList extends EasCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
|
|
||||||
const getAllUpdateChannelForAppResult = await getAllUpdateChannelForAppAsync({
|
const getAllUpdateChannelForAppResult = await getAllUpdateChannelForAppAsync({
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
|
|
||||||
@@ -7,6 +6,7 @@ import { GetChannelByNameForAppQuery, UpdateBranch } from '../../graphql/generat
|
|||||||
import { BranchQuery } from '../../graphql/queries/BranchQuery';
|
import { BranchQuery } from '../../graphql/queries/BranchQuery';
|
||||||
import { ChannelQuery } from '../../graphql/queries/ChannelQuery';
|
import { ChannelQuery } from '../../graphql/queries/ChannelQuery';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import {
|
import {
|
||||||
findProjectRootAsync,
|
findProjectRootAsync,
|
||||||
getProjectFullNameAsync,
|
getProjectFullNameAsync,
|
||||||
@@ -344,7 +344,7 @@ export default class ChannelRollout extends EasCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const fullName = await getProjectFullNameAsync(exp);
|
const fullName = await getProjectFullNameAsync(exp);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
@@ -7,6 +6,7 @@ import Table from 'cli-table3';
|
|||||||
import EasCommand from '../../commandUtils/EasCommand';
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
import { ChannelQuery } from '../../graphql/queries/ChannelQuery';
|
import { ChannelQuery } from '../../graphql/queries/ChannelQuery';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
||||||
import { promptAsync } from '../../prompts';
|
import { promptAsync } from '../../prompts';
|
||||||
import {
|
import {
|
||||||
@@ -45,7 +45,7 @@ export function getBranchMapping(branchMappingString?: string): {
|
|||||||
let branchMapping: BranchMapping;
|
let branchMapping: BranchMapping;
|
||||||
try {
|
try {
|
||||||
branchMapping = JSON.parse(branchMappingString);
|
branchMapping = JSON.parse(branchMappingString);
|
||||||
} catch (e) {
|
} catch {
|
||||||
throw new Error(`Could not parse branchMapping string into a JSON: "${branchMappingString}"`);
|
throw new Error(`Could not parse branchMapping string into a JSON: "${branchMappingString}"`);
|
||||||
}
|
}
|
||||||
assert(branchMapping, 'Branch Mapping must be defined.');
|
assert(branchMapping, 'Branch Mapping must be defined.');
|
||||||
@@ -165,7 +165,7 @@ export default class ChannelView extends EasCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
|
|
||||||
if (!channelName) {
|
if (!channelName) {
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import { appPlatformEmojis } from '../platform';
|
|||||||
import { getExpoConfig } from '../project/expoConfig';
|
import { getExpoConfig } from '../project/expoConfig';
|
||||||
import { findProjectRootAsync } from '../project/projectUtils';
|
import { findProjectRootAsync } from '../project/projectUtils';
|
||||||
import { selectAsync } from '../prompts';
|
import { selectAsync } from '../prompts';
|
||||||
import { handleDeprecatedEasJsonAsync } from './build';
|
|
||||||
|
|
||||||
export default class Config extends EasCommand {
|
export default class Config extends EasCommand {
|
||||||
static description = 'display project configuration (app.json + eas.json)';
|
static description = 'display project configuration (app.json + eas.json)';
|
||||||
@@ -31,7 +30,6 @@ export default class Config extends EasCommand {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
await handleDeprecatedEasJsonAsync(projectDir, false);
|
|
||||||
|
|
||||||
const reader = new EasJsonReader(projectDir);
|
const reader = new EasJsonReader(projectDir);
|
||||||
const profileName =
|
const profileName =
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Device, DeviceStatus } from '@expo/apple-utils';
|
import { Device, DeviceStatus } from '@expo/apple-utils';
|
||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
|
|
||||||
@@ -17,6 +16,7 @@ import formatDevice from '../../devices/utils/formatDevice';
|
|||||||
import { AppleDevice, Maybe } from '../../graphql/generated';
|
import { AppleDevice, Maybe } from '../../graphql/generated';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
import { ora } from '../../ora';
|
import { ora } from '../../ora';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import { findProjectRootAsync, getProjectAccountNameAsync } from '../../project/projectUtils';
|
import { findProjectRootAsync, getProjectAccountNameAsync } from '../../project/projectUtils';
|
||||||
import { promptAsync, toggleConfirmAsync } from '../../prompts';
|
import { promptAsync, toggleConfirmAsync } from '../../prompts';
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ export default class DeviceDelete extends EasCommand {
|
|||||||
} = await this.parse(DeviceDelete);
|
} = await this.parse(DeviceDelete);
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const accountName = await getProjectAccountNameAsync(exp);
|
const accountName = await getProjectAccountNameAsync(exp);
|
||||||
|
|
||||||
if (!appleTeamIdentifier) {
|
if (!appleTeamIdentifier) {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
@@ -9,6 +8,7 @@ import { AppleTeamQuery } from '../../credentials/ios/api/graphql/queries/AppleT
|
|||||||
import formatDevice from '../../devices/utils/formatDevice';
|
import formatDevice from '../../devices/utils/formatDevice';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
import { Ora, ora } from '../../ora';
|
import { Ora, ora } from '../../ora';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import { findProjectRootAsync, getProjectAccountNameAsync } from '../../project/projectUtils';
|
import { findProjectRootAsync, getProjectAccountNameAsync } from '../../project/projectUtils';
|
||||||
import { promptAsync } from '../../prompts';
|
import { promptAsync } from '../../prompts';
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ export default class BuildList extends EasCommand {
|
|||||||
let appleTeamIdentifier = (await this.parse(BuildList)).flags['apple-team-id'];
|
let appleTeamIdentifier = (await this.parse(BuildList)).flags['apple-team-id'];
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const accountName = await getProjectAccountNameAsync(exp);
|
const accountName = await getProjectAccountNameAsync(exp);
|
||||||
|
|
||||||
let spinner: Ora;
|
let spinner: Ora;
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
|
|
||||||
import EasCommand from '../../commandUtils/EasCommand';
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
import { AppleDeviceQuery } from '../../credentials/ios/api/graphql/queries/AppleDeviceQuery';
|
import { AppleDeviceQuery } from '../../credentials/ios/api/graphql/queries/AppleDeviceQuery';
|
||||||
import formatDevice from '../../devices/utils/formatDevice';
|
import formatDevice from '../../devices/utils/formatDevice';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
import { ora } from '../../ora';
|
import { ora } from '../../ora';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import { findProjectRootAsync, getProjectAccountNameAsync } from '../../project/projectUtils';
|
import { findProjectRootAsync, getProjectAccountNameAsync } from '../../project/projectUtils';
|
||||||
|
|
||||||
export default class DeviceView extends EasCommand {
|
export default class DeviceView extends EasCommand {
|
||||||
@@ -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 projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const accountName = await getProjectAccountNameAsync(exp);
|
const accountName = await getProjectAccountNameAsync(exp);
|
||||||
|
|
||||||
const spinner = ora().start(`Fetching device details for ${UDID}…`);
|
const spinner = ora().start(`Fetching device details for ${UDID}…`);
|
||||||
|
|||||||
@@ -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';
|
||||||
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
|
import { CredentialsContext } from '../../credentials/context';
|
||||||
|
import Log, { learnMore } from '../../log';
|
||||||
|
import { createMetadataContextAsync } from '../../metadata/context';
|
||||||
|
import { downloadMetadataAsync } from '../../metadata/download';
|
||||||
|
import { handleMetadataError } from '../../metadata/errors';
|
||||||
|
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
||||||
|
import { ensureLoggedInAsync } from '../../user/actions';
|
||||||
|
|
||||||
|
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';
|
||||||
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
|
import { CredentialsContext } from '../../credentials/context';
|
||||||
|
import Log, { learnMore } from '../../log';
|
||||||
|
import { createMetadataContextAsync } from '../../metadata/context';
|
||||||
|
import { handleMetadataError } from '../../metadata/errors';
|
||||||
|
import { uploadMetadataAsync } from '../../metadata/upload';
|
||||||
|
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
||||||
|
import { ensureLoggedInAsync } from '../../user/actions';
|
||||||
|
|
||||||
|
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,10 +1,10 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
|
|
||||||
import EasCommand from '../../commandUtils/EasCommand';
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client';
|
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client';
|
||||||
import { AppInfoQuery, AppInfoQueryVariables } from '../../graphql/generated';
|
import { AppInfoQuery, AppInfoQueryVariables } from '../../graphql/generated';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
||||||
import formatFields from '../../utils/formatFields';
|
import formatFields from '../../utils/formatFields';
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ export default class ProjectInfo extends EasCommand {
|
|||||||
|
|
||||||
async runAsync(): Promise<void> {
|
async runAsync(): Promise<void> {
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
const { app } = await projectInfoByIdAsync(projectId);
|
const { app } = await projectInfoByIdAsync(projectId);
|
||||||
if (!app) {
|
if (!app) {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
|
|
||||||
import EasCommand from '../../commandUtils/EasCommand';
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import { findProjectRootAsync, setProjectIdAsync } from '../../project/projectUtils';
|
import { findProjectRootAsync, setProjectIdAsync } from '../../project/projectUtils';
|
||||||
|
|
||||||
export default class ProjectInit extends EasCommand {
|
export default class ProjectInit extends EasCommand {
|
||||||
@@ -11,7 +11,7 @@ export default class ProjectInit extends EasCommand {
|
|||||||
|
|
||||||
async runAsync(): Promise<void> {
|
async runAsync(): Promise<void> {
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
|
|
||||||
if (exp.extra?.eas?.projectId) {
|
if (exp.extra?.eas?.projectId) {
|
||||||
Log.error(
|
Log.error(
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
|
|
||||||
@@ -9,6 +8,7 @@ import {
|
|||||||
EnvironmentSecretsQuery,
|
EnvironmentSecretsQuery,
|
||||||
} from '../../graphql/queries/EnvironmentSecretsQuery';
|
} from '../../graphql/queries/EnvironmentSecretsQuery';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import {
|
import {
|
||||||
findProjectRootAsync,
|
findProjectRootAsync,
|
||||||
getProjectAccountNameAsync,
|
getProjectAccountNameAsync,
|
||||||
@@ -47,7 +47,7 @@ export default class EnvironmentSecretCreate extends EasCommand {
|
|||||||
} = await this.parse(EnvironmentSecretCreate);
|
} = await this.parse(EnvironmentSecretCreate);
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const accountName = await getProjectAccountNameAsync(exp);
|
const accountName = await getProjectAccountNameAsync(exp);
|
||||||
|
|
||||||
const { slug } = exp;
|
const { slug } = exp;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
|
|
||||||
import EasCommand from '../../commandUtils/EasCommand';
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
@@ -9,6 +8,7 @@ import {
|
|||||||
EnvironmentSecretsQuery,
|
EnvironmentSecretsQuery,
|
||||||
} from '../../graphql/queries/EnvironmentSecretsQuery';
|
} from '../../graphql/queries/EnvironmentSecretsQuery';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import {
|
import {
|
||||||
findProjectRootAsync,
|
findProjectRootAsync,
|
||||||
getProjectAccountNameAsync,
|
getProjectAccountNameAsync,
|
||||||
@@ -27,7 +27,7 @@ export default class EnvironmentSecretDelete extends EasCommand {
|
|||||||
|
|
||||||
async runAsync(): Promise<void> {
|
async runAsync(): Promise<void> {
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
const projectAccountName = await getProjectAccountNameAsync(exp);
|
const projectAccountName = await getProjectAccountNameAsync(exp);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import Table from 'cli-table3';
|
import Table from 'cli-table3';
|
||||||
import dateFormat from 'dateformat';
|
import dateFormat from 'dateformat';
|
||||||
@@ -6,6 +5,7 @@ import dateFormat from 'dateformat';
|
|||||||
import EasCommand from '../../commandUtils/EasCommand';
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
import { EnvironmentSecretsQuery } from '../../graphql/queries/EnvironmentSecretsQuery';
|
import { EnvironmentSecretsQuery } from '../../graphql/queries/EnvironmentSecretsQuery';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import {
|
import {
|
||||||
findProjectRootAsync,
|
findProjectRootAsync,
|
||||||
getProjectAccountNameAsync,
|
getProjectAccountNameAsync,
|
||||||
@@ -17,7 +17,7 @@ export default class EnvironmentSecretList extends EasCommand {
|
|||||||
|
|
||||||
async runAsync(): Promise<void> {
|
async runAsync(): Promise<void> {
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
const projectAccountName = await getProjectAccountNameAsync(exp);
|
const projectAccountName = await getProjectAccountNameAsync(exp);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { getConfig } from '@expo/config';
|
import { EasJsonReader } from '@expo/eas-json';
|
||||||
import { Errors, Flags } from '@oclif/core';
|
import { Errors, Flags } from '@oclif/core';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
selectRequestedPlatformAsync,
|
selectRequestedPlatformAsync,
|
||||||
toPlatforms,
|
toPlatforms,
|
||||||
} from '../platform';
|
} from '../platform';
|
||||||
|
import { getExpoConfig } from '../project/expoConfig';
|
||||||
import { findProjectRootAsync, getProjectIdAsync } from '../project/projectUtils';
|
import { findProjectRootAsync, getProjectIdAsync } from '../project/projectUtils';
|
||||||
import { SubmitArchiveFlags, createSubmissionContextAsync } from '../submit/context';
|
import { SubmitArchiveFlags, createSubmissionContextAsync } from '../submit/context';
|
||||||
import { submitAsync, waitToCompleteAsync } from '../submit/submit';
|
import { submitAsync, waitToCompleteAsync } from '../submit/submit';
|
||||||
@@ -89,13 +90,13 @@ export default class Submit extends EasCommand {
|
|||||||
const flags = await this.sanitizeFlagsAsync(rawFlags);
|
const flags = await this.sanitizeFlagsAsync(rawFlags);
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
|
|
||||||
const platforms = toPlatforms(flags.requestedPlatform);
|
const platforms = toPlatforms(flags.requestedPlatform);
|
||||||
const submissionProfiles = await getProfilesAsync({
|
const submissionProfiles = await getProfilesAsync({
|
||||||
type: 'submit',
|
type: 'submit',
|
||||||
projectDir,
|
easJsonReader: new EasJsonReader(projectDir),
|
||||||
platforms,
|
platforms,
|
||||||
profileName: flags.profile,
|
profileName: flags.profile,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ExpoConfig, getConfig, modifyConfigAsync } from '@expo/config';
|
import { ExpoConfig, modifyConfigAsync } from '@expo/config';
|
||||||
import { Platform, Workflow } from '@expo/eas-build-job';
|
import { Platform, Workflow } from '@expo/eas-build-job';
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
@@ -9,6 +9,7 @@ import EasCommand from '../../commandUtils/EasCommand';
|
|||||||
import { AppPlatform } from '../../graphql/generated';
|
import { AppPlatform } from '../../graphql/generated';
|
||||||
import Log, { learnMore } from '../../log';
|
import Log, { learnMore } from '../../log';
|
||||||
import { RequestedPlatform, appPlatformDisplayNames } from '../../platform';
|
import { RequestedPlatform, appPlatformDisplayNames } from '../../platform';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import {
|
import {
|
||||||
findProjectRootAsync,
|
findProjectRootAsync,
|
||||||
getProjectIdAsync,
|
getProjectIdAsync,
|
||||||
@@ -41,9 +42,7 @@ export default class UpdateConfigure extends EasCommand {
|
|||||||
const { flags } = await this.parse(UpdateConfigure);
|
const { flags } = await this.parse(UpdateConfigure);
|
||||||
const platform = flags.platform as RequestedPlatform;
|
const platform = flags.platform as RequestedPlatform;
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, {
|
const exp = getExpoConfig(projectDir);
|
||||||
skipSDKVersionRequirement: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!isExpoUpdatesInstalledOrAvailable(projectDir, exp.sdkVersion)) {
|
if (!isExpoUpdatesInstalledOrAvailable(projectDir, exp.sdkVersion)) {
|
||||||
await installExpoUpdatesAsync(projectDir);
|
await installExpoUpdatesAsync(projectDir);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ExpoConfig, getConfig } from '@expo/config';
|
import { ExpoConfig } from '@expo/config';
|
||||||
import { Updates } from '@expo/config-plugins';
|
import { Updates } from '@expo/config-plugins';
|
||||||
import { Platform, Workflow } from '@expo/eas-build-job';
|
import { Platform, Workflow } from '@expo/eas-build-job';
|
||||||
import { Errors, Flags } from '@oclif/core';
|
import { Errors, Flags } from '@oclif/core';
|
||||||
@@ -9,6 +9,7 @@ import gql from 'graphql-tag';
|
|||||||
import nullthrows from 'nullthrows';
|
import nullthrows from 'nullthrows';
|
||||||
|
|
||||||
import { getEASUpdateURL } from '../../api';
|
import { getEASUpdateURL } from '../../api';
|
||||||
|
import { getUpdateGroupUrl } from '../../build/utils/url';
|
||||||
import EasCommand from '../../commandUtils/EasCommand';
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
import fetch from '../../fetch';
|
import fetch from '../../fetch';
|
||||||
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client';
|
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client';
|
||||||
@@ -25,10 +26,12 @@ import {
|
|||||||
} from '../../graphql/generated';
|
} from '../../graphql/generated';
|
||||||
import { PublishMutation } from '../../graphql/mutations/PublishMutation';
|
import { PublishMutation } from '../../graphql/mutations/PublishMutation';
|
||||||
import { UpdateQuery } from '../../graphql/queries/UpdateQuery';
|
import { UpdateQuery } from '../../graphql/queries/UpdateQuery';
|
||||||
import Log from '../../log';
|
import Log, { link } from '../../log';
|
||||||
import { ora } from '../../ora';
|
import { ora } from '../../ora';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import {
|
import {
|
||||||
findProjectRootAsync,
|
findProjectRootAsync,
|
||||||
|
getProjectAccountName,
|
||||||
getProjectIdAsync,
|
getProjectIdAsync,
|
||||||
installExpoUpdatesAsync,
|
installExpoUpdatesAsync,
|
||||||
isExpoUpdatesInstalledOrAvailable,
|
isExpoUpdatesInstalledOrAvailable,
|
||||||
@@ -43,6 +46,7 @@ import {
|
|||||||
import { resolveWorkflowAsync } from '../../project/workflow';
|
import { resolveWorkflowAsync } from '../../project/workflow';
|
||||||
import { confirmAsync, promptAsync, selectAsync } from '../../prompts';
|
import { confirmAsync, promptAsync, selectAsync } from '../../prompts';
|
||||||
import { formatUpdate } from '../../update/utils';
|
import { formatUpdate } from '../../update/utils';
|
||||||
|
import { ensureLoggedInAsync } from '../../user/actions';
|
||||||
import {
|
import {
|
||||||
checkManifestBodyAgainstUpdateInfoGroup,
|
checkManifestBodyAgainstUpdateInfoGroup,
|
||||||
getCodeSigningInfoAsync,
|
getCodeSigningInfoAsync,
|
||||||
@@ -58,7 +62,7 @@ import { listBranchesAsync } from '../branch/list';
|
|||||||
import { createUpdateChannelOnAppAsync } from '../channel/create';
|
import { createUpdateChannelOnAppAsync } from '../channel/create';
|
||||||
|
|
||||||
export const defaultPublishPlatforms: PublishPlatform[] = ['android', 'ios'];
|
export const defaultPublishPlatforms: PublishPlatform[] = ['android', 'ios'];
|
||||||
type PlatformFlag = PublishPlatform | 'all';
|
export type PublishPlatformFlag = PublishPlatform | 'all';
|
||||||
|
|
||||||
async function getUpdateGroupAsync({
|
async function getUpdateGroupAsync({
|
||||||
group,
|
group,
|
||||||
@@ -116,12 +120,16 @@ async function ensureChannelExistsAsync({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function ensureBranchExistsAsync({
|
export async function ensureBranchExistsAsync({
|
||||||
appId,
|
appId,
|
||||||
name: branchName,
|
name: branchName,
|
||||||
|
limit,
|
||||||
|
offset,
|
||||||
}: {
|
}: {
|
||||||
appId: string;
|
appId: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
limit?: number;
|
||||||
|
offset?: number;
|
||||||
}): Promise<{
|
}): Promise<{
|
||||||
id: string;
|
id: string;
|
||||||
updates: Exclude<
|
updates: Exclude<
|
||||||
@@ -132,6 +140,8 @@ async function ensureBranchExistsAsync({
|
|||||||
const { app } = await UpdateQuery.viewBranchAsync({
|
const { app } = await UpdateQuery.viewBranchAsync({
|
||||||
appId,
|
appId,
|
||||||
name: branchName,
|
name: branchName,
|
||||||
|
limit,
|
||||||
|
offset,
|
||||||
});
|
});
|
||||||
const updateBranch = app?.byId.updateBranchByName;
|
const updateBranch = app?.byId.updateBranchByName;
|
||||||
if (updateBranch) {
|
if (updateBranch) {
|
||||||
@@ -220,18 +230,16 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
enableJsonOutput();
|
enableJsonOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
const platformFlag = platform as PlatformFlag;
|
const platformFlag = platform as PublishPlatformFlag;
|
||||||
// If a group was specified, that means we are republishing it.
|
// If a group was specified, that means we are republishing it.
|
||||||
republish = group ? true : republish;
|
republish = group ? true : republish;
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, {
|
const exp = getExpoConfig(projectDir, {
|
||||||
skipSDKVersionRequirement: true,
|
|
||||||
isPublicConfig: true,
|
isPublicConfig: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { exp: expPrivate } = getConfig(projectDir, {
|
const expPrivate = getExpoConfig(projectDir, {
|
||||||
skipSDKVersionRequirement: true,
|
|
||||||
isPublicConfig: false,
|
isPublicConfig: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -310,13 +318,10 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
assert(branchName, 'Branch name must be specified.');
|
assert(branchName, 'Branch name must be specified.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const { id: branchId, updates } = await ensureBranchExistsAsync({
|
|
||||||
appId: projectId,
|
|
||||||
name: branchName,
|
|
||||||
});
|
|
||||||
|
|
||||||
let unsortedUpdateInfoGroups: UpdateInfoGroup = {};
|
let unsortedUpdateInfoGroups: UpdateInfoGroup = {};
|
||||||
let oldMessage: string, oldRuntimeVersion: string;
|
let oldMessage: string, oldRuntimeVersion: string;
|
||||||
|
let uploadedAssetCount = 0;
|
||||||
|
|
||||||
if (republish) {
|
if (republish) {
|
||||||
// If we are republishing, we don't need to worry about building the bundle or uploading the assets.
|
// If we are republishing, we don't need to worry about building the bundle or uploading the assets.
|
||||||
// Instead we get the `updateInfoGroup` from the update we wish to republish.
|
// Instead we get the `updateInfoGroup` from the update we wish to republish.
|
||||||
@@ -336,26 +341,12 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
throw new Error('You must specify the update group to republish.');
|
throw new Error('You must specify the update group to republish.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateGroups = uniqBy(updates, u => u.group)
|
updatesToRepublish = await getUpdatesToRepublishInteractiveAsync(
|
||||||
.filter(update => {
|
projectId,
|
||||||
// Only show groups that have updates on the specified platform(s).
|
branchName,
|
||||||
return platformFlag === 'all' || update.platform === platformFlag;
|
platformFlag,
|
||||||
})
|
50
|
||||||
.map(update => ({
|
|
||||||
title: formatUpdateTitle(update),
|
|
||||||
value: update.group,
|
|
||||||
}));
|
|
||||||
if (updateGroups.length === 0) {
|
|
||||||
throw new Error(
|
|
||||||
`There are no updates on branch "${branchName}" published on the platform(s) ${platformFlag}. Did you mean to publish a new update instead?`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const selectedUpdateGroup = await selectAsync<string>(
|
|
||||||
'which update would you like to republish?',
|
|
||||||
updateGroups
|
|
||||||
);
|
);
|
||||||
updatesToRepublish = updates.filter(update => update.group === selectedUpdateGroup);
|
|
||||||
}
|
}
|
||||||
const updatesToRepublishFilteredByPlatform = updatesToRepublish.filter(
|
const updatesToRepublishFilteredByPlatform = updatesToRepublish.filter(
|
||||||
// Only republish to the specified platforms
|
// Only republish to the specified platforms
|
||||||
@@ -363,7 +354,7 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
);
|
);
|
||||||
if (updatesToRepublishFilteredByPlatform.length === 0) {
|
if (updatesToRepublishFilteredByPlatform.length === 0) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`There are no updates on branch "${branchName}" published on the platform(s) "${platformFlag}" with group ID "${
|
`There are no updates on branch "${branchName}" published for the platform(s) "${platformFlag}" with group ID "${
|
||||||
group ? group : updatesToRepublish[0].group
|
group ? group : updatesToRepublish[0].group
|
||||||
}". Did you mean to publish a new update instead?`
|
}". Did you mean to publish a new update instead?`
|
||||||
);
|
);
|
||||||
@@ -450,15 +441,28 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
try {
|
try {
|
||||||
const platforms = platformFlag === 'all' ? defaultPublishPlatforms : [platformFlag];
|
const platforms = platformFlag === 'all' ? defaultPublishPlatforms : [platformFlag];
|
||||||
const assets = await collectAssetsAsync({ inputDir: inputDir!, platforms });
|
const assets = await collectAssetsAsync({ inputDir: inputDir!, platforms });
|
||||||
await uploadAssetsAsync(assets);
|
const { uniqueUploadedAssetCount } = await uploadAssetsAsync(
|
||||||
|
assets,
|
||||||
|
(totalAssets, missingAssets) => {
|
||||||
|
assetSpinner.text = `Uploading assets. Finished (${
|
||||||
|
totalAssets - missingAssets
|
||||||
|
}/${totalAssets})`;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
uploadedAssetCount = uniqueUploadedAssetCount;
|
||||||
unsortedUpdateInfoGroups = await buildUnsortedUpdateInfoGroupAsync(assets, exp);
|
unsortedUpdateInfoGroups = await buildUnsortedUpdateInfoGroupAsync(assets, exp);
|
||||||
assetSpinner.succeed('Uploaded assets!');
|
const uploadAssetSuccessMessage = uploadedAssetCount
|
||||||
|
? `Uploaded ${uploadedAssetCount} ${uploadedAssetCount === 1 ? 'asset' : 'assets'}!`
|
||||||
|
: `Uploading assets skipped -- no new assets found!`;
|
||||||
|
assetSpinner.succeed(uploadAssetSuccessMessage);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
assetSpinner.fail('Failed to upload assets');
|
assetSpinner.fail('Failed to upload assets');
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const truncatedMessage = truncatePublishUpdateMessage(message!);
|
||||||
|
|
||||||
const runtimeToPlatformMapping: Record<string, string[]> = {};
|
const runtimeToPlatformMapping: Record<string, string[]> = {};
|
||||||
for (const runtime of new Set(Object.values(runtimeVersions))) {
|
for (const runtime of new Set(Object.values(runtimeVersions))) {
|
||||||
runtimeToPlatformMapping[runtime] = Object.entries(runtimeVersions)
|
runtimeToPlatformMapping[runtime] = Object.entries(runtimeVersions)
|
||||||
@@ -466,6 +470,12 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
.map(pair => pair[0]);
|
.map(pair => pair[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { id: branchId } = await ensureBranchExistsAsync({
|
||||||
|
appId: projectId,
|
||||||
|
name: branchName,
|
||||||
|
limit: 0,
|
||||||
|
});
|
||||||
|
|
||||||
// Sort the updates into different groups based on their platform specific runtime versions
|
// Sort the updates into different groups based on their platform specific runtime versions
|
||||||
const updateGroups: PublishUpdateGroupInput[] = Object.entries(runtimeToPlatformMapping).map(
|
const updateGroups: PublishUpdateGroupInput[] = Object.entries(runtimeToPlatformMapping).map(
|
||||||
([runtime, platforms]) => {
|
([runtime, platforms]) => {
|
||||||
@@ -485,7 +495,7 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
branchId,
|
branchId,
|
||||||
updateInfoGroup: localUpdateInfoGroup,
|
updateInfoGroup: localUpdateInfoGroup,
|
||||||
runtimeVersion: republish ? oldRuntimeVersion : runtime,
|
runtimeVersion: republish ? oldRuntimeVersion : runtime,
|
||||||
message,
|
message: truncatedMessage,
|
||||||
awaitingCodeSigningInfo: !!codeSigningInfo,
|
awaitingCodeSigningInfo: !!codeSigningInfo,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -555,20 +565,36 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
|
|
||||||
Log.addNewLineIfNone();
|
Log.addNewLineIfNone();
|
||||||
for (const runtime of new Set(Object.values(runtimeVersions))) {
|
for (const runtime of new Set(Object.values(runtimeVersions))) {
|
||||||
const platforms = newUpdates
|
const newUpdatesForRuntimeVersion = newUpdates.filter(
|
||||||
.filter(update => update.runtimeVersion === runtime)
|
update => update.runtimeVersion === runtime
|
||||||
.map(update => update.platform);
|
);
|
||||||
const newUpdate = newUpdates.find(update => update.runtimeVersion === runtime);
|
if (!newUpdatesForRuntimeVersion.length) {
|
||||||
if (!newUpdate) {
|
|
||||||
throw new Error(`Publish response is missing updates with runtime ${runtime}.`);
|
throw new Error(`Publish response is missing updates with runtime ${runtime}.`);
|
||||||
}
|
}
|
||||||
|
const platforms = newUpdatesForRuntimeVersion.map(update => update.platform);
|
||||||
|
const newAndroidUpdate = newUpdatesForRuntimeVersion.find(
|
||||||
|
update => update.platform === 'android'
|
||||||
|
);
|
||||||
|
const newIosUpdate = newUpdatesForRuntimeVersion.find(update => update.platform === 'ios');
|
||||||
|
const updateGroupId = newUpdatesForRuntimeVersion[0].group;
|
||||||
|
|
||||||
|
const projectName = exp.slug;
|
||||||
|
const accountName = getProjectAccountName(exp, await ensureLoggedInAsync());
|
||||||
|
const updateGroupUrl = getUpdateGroupUrl(accountName, projectName, updateGroupId);
|
||||||
|
const updateGroupLink = link(updateGroupUrl, { dim: false });
|
||||||
|
|
||||||
Log.log(
|
Log.log(
|
||||||
formatFields([
|
formatFields([
|
||||||
{ label: 'branch', value: branchName },
|
{ label: 'Branch', value: branchName },
|
||||||
{ label: 'runtime version', value: runtime },
|
{ label: 'Runtime version', value: runtime },
|
||||||
{ label: 'platform', value: platforms.join(', ') },
|
{ label: 'Platform', value: platforms.join(', ') },
|
||||||
{ label: 'update group ID', value: newUpdate.group },
|
{ label: 'Update group ID', value: updateGroupId },
|
||||||
{ label: 'message', value: message! },
|
...(newAndroidUpdate
|
||||||
|
? [{ label: 'Android update ID', value: newAndroidUpdate.id }]
|
||||||
|
: []),
|
||||||
|
...(newIosUpdate ? [{ label: 'iOS update ID', value: newIosUpdate.id }] : []),
|
||||||
|
{ label: 'Message', value: truncatedMessage },
|
||||||
|
{ label: 'Website link', value: updateGroupLink },
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
Log.addNewLineIfNone();
|
Log.addNewLineIfNone();
|
||||||
@@ -577,9 +603,76 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getUpdatesToRepublishInteractiveAsync(
|
||||||
|
projectId: string,
|
||||||
|
branchName: string,
|
||||||
|
platformFlag: string,
|
||||||
|
pageSize: number,
|
||||||
|
offset: number = 0,
|
||||||
|
cumulativeUpdates: Exclude<
|
||||||
|
Exclude<ViewBranchUpdatesQuery['app'], null | undefined>['byId']['updateBranchByName'],
|
||||||
|
null | undefined
|
||||||
|
>['updates'] = []
|
||||||
|
): Promise<
|
||||||
|
Exclude<
|
||||||
|
Exclude<ViewBranchUpdatesQuery['app'], null | undefined>['byId']['updateBranchByName'],
|
||||||
|
null | undefined
|
||||||
|
>['updates']
|
||||||
|
> {
|
||||||
|
const fetchMoreValue = '_fetchMore';
|
||||||
|
|
||||||
|
const { updates } = await ensureBranchExistsAsync({
|
||||||
|
appId: projectId,
|
||||||
|
name: branchName,
|
||||||
|
limit: pageSize + 1, // fetch an extra item so we know if there are additional pages
|
||||||
|
offset,
|
||||||
|
});
|
||||||
|
cumulativeUpdates = [
|
||||||
|
...cumulativeUpdates,
|
||||||
|
// drop that extra item used for pagination from our render logic
|
||||||
|
...updates.slice(0, updates.length - 1),
|
||||||
|
];
|
||||||
|
const cumulativeUpdatesForTargetPlatforms =
|
||||||
|
platformFlag === 'all'
|
||||||
|
? cumulativeUpdates
|
||||||
|
: cumulativeUpdates.filter(update => {
|
||||||
|
// Only show groups that have updates on the specified platform(s).
|
||||||
|
return update.platform === platformFlag;
|
||||||
|
});
|
||||||
|
const updateGroups = uniqBy(cumulativeUpdatesForTargetPlatforms, u => u.group).map(update => ({
|
||||||
|
title: formatUpdateTitle(update),
|
||||||
|
value: update.group,
|
||||||
|
}));
|
||||||
|
if (!updateGroups.length) {
|
||||||
|
throw new Error(
|
||||||
|
`There are no updates on branch "${branchName}" published for the platform(s) ${platformFlag}. Did you mean to publish a new update instead?`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updates.length > pageSize) {
|
||||||
|
updateGroups.push({ title: 'Next page...', value: fetchMoreValue });
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedUpdateGroup = await selectAsync<string>(
|
||||||
|
'Which update would you like to republish?',
|
||||||
|
updateGroups
|
||||||
|
);
|
||||||
|
if (selectedUpdateGroup === fetchMoreValue) {
|
||||||
|
return await getUpdatesToRepublishInteractiveAsync(
|
||||||
|
projectId,
|
||||||
|
branchName,
|
||||||
|
platformFlag,
|
||||||
|
pageSize,
|
||||||
|
offset + pageSize,
|
||||||
|
cumulativeUpdates
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return cumulativeUpdates.filter(update => update.group === selectedUpdateGroup);
|
||||||
|
}
|
||||||
|
|
||||||
async function getRuntimeVersionObjectAsync(
|
async function getRuntimeVersionObjectAsync(
|
||||||
exp: ExpoConfig,
|
exp: ExpoConfig,
|
||||||
platformFlag: PlatformFlag,
|
platformFlag: PublishPlatformFlag,
|
||||||
projectDir: string
|
projectDir: string
|
||||||
): Promise<Record<string, string>> {
|
): Promise<Record<string, string>> {
|
||||||
const platforms = (platformFlag === 'all' ? ['android', 'ios'] : [platformFlag]) as Platform[];
|
const platforms = (platformFlag === 'all' ? ['android', 'ios'] : [platformFlag]) as Platform[];
|
||||||
@@ -646,3 +739,11 @@ async function checkEASUpdateURLIsSetAsync(exp: ExpoConfig): Promise<void> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const truncatePublishUpdateMessage = (originalMessage: string): string => {
|
||||||
|
if (originalMessage.length > 1024) {
|
||||||
|
Log.warn('Update message exceeds the allowed 1024 character limit. Truncating message...');
|
||||||
|
return originalMessage.substring(0, 1021) + '...';
|
||||||
|
}
|
||||||
|
return originalMessage;
|
||||||
|
};
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
@@ -8,6 +7,7 @@ import EasCommand from '../../commandUtils/EasCommand';
|
|||||||
import { ViewAllUpdatesQuery } from '../../graphql/generated';
|
import { ViewAllUpdatesQuery } from '../../graphql/generated';
|
||||||
import { UpdateQuery } from '../../graphql/queries/UpdateQuery';
|
import { UpdateQuery } from '../../graphql/queries/UpdateQuery';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
||||||
import { promptAsync } from '../../prompts';
|
import { promptAsync } from '../../prompts';
|
||||||
import { FormatUpdateParameter, UPDATE_COLUMNS, formatUpdate } from '../../update/utils';
|
import { FormatUpdateParameter, UPDATE_COLUMNS, formatUpdate } from '../../update/utils';
|
||||||
@@ -50,7 +50,7 @@ export default class BranchView extends EasCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
|
|
||||||
let updateGroupDescriptions: UpdateGroupDescription[];
|
let updateGroupDescriptions: UpdateGroupDescription[];
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
|
|
||||||
import EasCommand from '../../commandUtils/EasCommand';
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
import { WebhookType } from '../../graphql/generated';
|
import { WebhookType } from '../../graphql/generated';
|
||||||
import { WebhookMutation } from '../../graphql/mutations/WebhookMutation';
|
import { WebhookMutation } from '../../graphql/mutations/WebhookMutation';
|
||||||
import { ora } from '../../ora';
|
import { ora } from '../../ora';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
||||||
import { prepareInputParamsAsync } from '../../webhooks/input';
|
import { prepareInputParamsAsync } from '../../webhooks/input';
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ export default class WebhookCreate extends EasCommand {
|
|||||||
const webhookInputParams = await prepareInputParamsAsync(flags);
|
const webhookInputParams = await prepareInputParamsAsync(flags);
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
|
|
||||||
const spinner = ora('Creating a webhook').start();
|
const spinner = ora('Creating a webhook').start();
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import nullthrows from 'nullthrows';
|
import nullthrows from 'nullthrows';
|
||||||
@@ -9,6 +8,7 @@ import { WebhookMutation } from '../../graphql/mutations/WebhookMutation';
|
|||||||
import { WebhookQuery } from '../../graphql/queries/WebhookQuery';
|
import { WebhookQuery } from '../../graphql/queries/WebhookQuery';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
import { ora } from '../../ora';
|
import { ora } from '../../ora';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUtils';
|
||||||
import { promptAsync, toggleConfirmAsync } from '../../prompts';
|
import { promptAsync, toggleConfirmAsync } from '../../prompts';
|
||||||
import { formatWebhook } from '../../webhooks/formatWebhook';
|
import { formatWebhook } from '../../webhooks/formatWebhook';
|
||||||
@@ -30,7 +30,7 @@ export default class WebhookDelete extends EasCommand {
|
|||||||
} = await this.parse(WebhookDelete);
|
} = await this.parse(WebhookDelete);
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
|
|
||||||
let webhook: WebhookFragment | undefined =
|
let webhook: WebhookFragment | undefined =
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getConfig } from '@expo/config';
|
|
||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
|
|
||||||
@@ -7,6 +6,7 @@ import { WebhookType } from '../../graphql/generated';
|
|||||||
import { WebhookQuery } from '../../graphql/queries/WebhookQuery';
|
import { WebhookQuery } from '../../graphql/queries/WebhookQuery';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
import { ora } from '../../ora';
|
import { ora } from '../../ora';
|
||||||
|
import { getExpoConfig } from '../../project/expoConfig';
|
||||||
import {
|
import {
|
||||||
findProjectRootAsync,
|
findProjectRootAsync,
|
||||||
getProjectFullNameAsync,
|
getProjectFullNameAsync,
|
||||||
@@ -30,7 +30,7 @@ export default class WebhookList extends EasCommand {
|
|||||||
} = await this.parse(WebhookList);
|
} = await this.parse(WebhookList);
|
||||||
|
|
||||||
const projectDir = await findProjectRootAsync();
|
const projectDir = await findProjectRootAsync();
|
||||||
const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true });
|
const exp = getExpoConfig(projectDir);
|
||||||
const projectId = await getProjectIdAsync(exp);
|
const projectId = await getProjectIdAsync(exp);
|
||||||
const projectFullName = await getProjectFullNameAsync(exp);
|
const projectFullName = await getProjectFullNameAsync(exp);
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ function fileIsServiceAccountKey(keyJsonPath: string): boolean {
|
|||||||
try {
|
try {
|
||||||
readAndValidateServiceAccountKey(keyJsonPath);
|
readAndValidateServiceAccountKey(keyJsonPath);
|
||||||
return true;
|
return true;
|
||||||
} catch (err: any) {
|
} catch {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export async function keytoolCommandExistsAsync(): Promise<boolean> {
|
|||||||
try {
|
try {
|
||||||
await spawnAsync('keytool');
|
await spawnAsync('keytool');
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ function isPKCSKeystore(keystore: Keystore): boolean {
|
|||||||
try {
|
try {
|
||||||
parsePKCS12(keystore.keystore, keystore.keystorePassword);
|
parsePKCS12(keystore.keystore, keystore.keystorePassword);
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ function isJKSKeystore(keystore: Keystore): boolean {
|
|||||||
try {
|
try {
|
||||||
jks.parseJks(Buffer.from(keystore.keystore, 'base64'), keystore.keystorePassword);
|
jks.parseJks(Buffer.from(keystore.keystore, 'base64'), keystore.keystorePassword);
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ExpoConfig, getConfig } from '@expo/config';
|
import { ExpoConfig } from '@expo/config';
|
||||||
import { Env } from '@expo/eas-build-job';
|
import { Env } from '@expo/eas-build-job';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ export class CredentialsContext {
|
|||||||
): ExpoConfig | null {
|
): ExpoConfig | null {
|
||||||
try {
|
try {
|
||||||
return getExpoConfig(projectDir, { env });
|
return getExpoConfig(projectDir, { env });
|
||||||
} catch (error) {
|
} catch {
|
||||||
// ignore error, context might be created outside of expo project
|
// ignore error, context might be created outside of expo project
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -70,7 +70,7 @@ export class CredentialsContext {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// trigger getConfig error
|
// trigger getConfig error
|
||||||
getConfig(this.options.projectDir, { skipSDKVersionRequirement: true });
|
getExpoConfig(this.options.projectDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
public logOwnerAndProject(): void {
|
public logOwnerAndProject(): void {
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ export async function readRawAsync(
|
|||||||
try {
|
try {
|
||||||
const credentialsJSONContents = await fs.readFile(credentialsJsonFilePath, 'utf8');
|
const credentialsJSONContents = await fs.readFile(credentialsJsonFilePath, 'utf8');
|
||||||
return JSON.parse(credentialsJSONContents);
|
return JSON.parse(credentialsJSONContents);
|
||||||
} catch (err) {
|
} catch {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`credentials.json must exist in the project root directory and contain a valid JSON`
|
`credentials.json must exist in the project root directory and contain a valid JSON`
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -254,11 +254,11 @@ export class SetUpAdhocProvisioningProfile {
|
|||||||
ctx: CredentialsContext,
|
ctx: CredentialsContext,
|
||||||
appleTeam: AppleTeamFragment
|
appleTeam: AppleTeamFragment
|
||||||
): Promise<AppleDeviceFragment[]> {
|
): Promise<AppleDeviceFragment[]> {
|
||||||
const action = new DeviceCreateAction(this.app.account, appleTeam);
|
const action = new DeviceCreateAction(ctx.appStore, this.app.account, appleTeam);
|
||||||
const method = await action.runAsync();
|
const method = await action.runAsync();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (method !== RegistrationMethod.INPUT) {
|
if (method === RegistrationMethod.WEBSITE) {
|
||||||
Log.newLine();
|
Log.newLine();
|
||||||
Log.log(chalk.bold("Press any key if you've already finished device registration."));
|
Log.log(chalk.bold("Press any key if you've already finished device registration."));
|
||||||
await pressAnyKeyToContinueAsync();
|
await pressAnyKeyToContinueAsync();
|
||||||
|
|||||||
@@ -18,6 +18,43 @@ describe(assertValidOptions, () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe(syncCapabilitiesForEntitlementsAsync, () => {
|
describe(syncCapabilitiesForEntitlementsAsync, () => {
|
||||||
|
it(`does not disable associated domains when MDM managed domains is active`, async () => {
|
||||||
|
const ctx = { providerId: 123195, teamId: 'MyteamId' };
|
||||||
|
// https://forums.expo.dev/t/eas-build-failed-on-ios-associated-domains-capability/61662/5
|
||||||
|
const capabilities = [
|
||||||
|
{
|
||||||
|
id: 'U78L9459DG_MDM_MANAGED_ASSOCIATED_DOMAINS',
|
||||||
|
attributes: {
|
||||||
|
ownerType: 'BUNDLE',
|
||||||
|
settings: null,
|
||||||
|
editable: true,
|
||||||
|
inputs: null,
|
||||||
|
enabled: true,
|
||||||
|
responseId: '77eb74ad-7c24-48de-9d35-1fabb4c5afd9',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
].map(({ id, attributes }) => new BundleIdCapability(ctx, id, attributes as any));
|
||||||
|
|
||||||
|
const entitlements = {
|
||||||
|
'com.apple.developer.associated-domains': ['applinks:packagename.fr'],
|
||||||
|
};
|
||||||
|
|
||||||
|
const bundleId = {
|
||||||
|
getBundleIdCapabilitiesAsync: jest.fn(() => capabilities),
|
||||||
|
updateBundleIdCapabilityAsync: jest.fn(),
|
||||||
|
id: 'XXX',
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
await syncCapabilitiesForEntitlementsAsync(bundleId, entitlements);
|
||||||
|
|
||||||
|
expect(bundleId.updateBundleIdCapabilityAsync).toBeCalledWith([
|
||||||
|
{
|
||||||
|
capabilityType: 'ASSOCIATED_DOMAINS',
|
||||||
|
option: 'ON',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
it('enables all capabilities', async () => {
|
it('enables all capabilities', async () => {
|
||||||
const bundleId = {
|
const bundleId = {
|
||||||
getBundleIdCapabilitiesAsync: jest.fn(() => []),
|
getBundleIdCapabilitiesAsync: jest.fn(() => []),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { JSONObject } from '@expo/json-file';
|
import { JSONObject } from '@expo/json-file';
|
||||||
|
import type { XCBuildConfiguration } from 'xcode';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CommonIosAppCredentialsFragment,
|
CommonIosAppCredentialsFragment,
|
||||||
@@ -17,6 +18,7 @@ export interface Target {
|
|||||||
bundleIdentifier: string;
|
bundleIdentifier: string;
|
||||||
parentBundleIdentifier?: string;
|
parentBundleIdentifier?: string;
|
||||||
entitlements: JSONObject;
|
entitlements: JSONObject;
|
||||||
|
buildSettings?: XCBuildConfiguration['buildSettings'];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TargetCredentials {
|
export interface TargetCredentials {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ describe(getCertData, () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe(forge.pkcs12.pkcs12FromAsn1, () => {
|
describe('forge.pkcs12.pkcs12FromAsn1', () => {
|
||||||
describe('when using p12 created from keychain', () => {
|
describe('when using p12 created from keychain', () => {
|
||||||
it('throws if empty string is passed', async () => {
|
it('throws if empty string is passed', async () => {
|
||||||
const p12Der = forge.util.decode64(testDistributionCertificateEmptyPasswordBase64);
|
const p12Der = forge.util.decode64(testDistributionCertificateEmptyPasswordBase64);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export function parse(dataBase64: string): PlistObject {
|
|||||||
const buffer = Buffer.from(dataBase64, 'base64');
|
const buffer = Buffer.from(dataBase64, 'base64');
|
||||||
const profile = buffer.toString('utf8');
|
const profile = buffer.toString('utf8');
|
||||||
return plist.parse(profile) as PlistObject;
|
return plist.parse(profile) as PlistObject;
|
||||||
} catch (error) {
|
} catch {
|
||||||
throw new Error('Provisioning profile is malformed');
|
throw new Error('Provisioning profile is malformed');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ function validateProvisioningProfileWithoutApple(
|
|||||||
Log.warn('Provisioning Profile has expired.');
|
Log.warn('Provisioning Profile has expired.');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch {
|
||||||
Log.warn('Provisioning Profile is malformed.');
|
Log.warn('Provisioning Profile is malformed.');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export const runDeveloperPortalMethodAsync = jest.fn();
|
||||||
@@ -1,13 +1,17 @@
|
|||||||
import prompts from 'prompts';
|
import prompts from 'prompts';
|
||||||
|
import { instance, mock } from 'ts-mockito';
|
||||||
|
|
||||||
|
import AppStoreApi from '../../../../credentials/ios/appstore/AppStoreApi';
|
||||||
import { Account } from '../../../../user/Account';
|
import { Account } from '../../../../user/Account';
|
||||||
import DeviceCreateAction, { RegistrationMethod } from '../action';
|
import DeviceCreateAction, { RegistrationMethod } from '../action';
|
||||||
|
import { runDeveloperPortalMethodAsync } from '../developerPortalMethod';
|
||||||
import { runInputMethodAsync } from '../inputMethod';
|
import { runInputMethodAsync } from '../inputMethod';
|
||||||
import { runRegistrationUrlMethodAsync } from '../registrationUrlMethod';
|
import { runRegistrationUrlMethodAsync } from '../registrationUrlMethod';
|
||||||
|
|
||||||
jest.mock('prompts');
|
jest.mock('prompts');
|
||||||
jest.mock('../registrationUrlMethod');
|
jest.mock('../developerPortalMethod');
|
||||||
jest.mock('../inputMethod');
|
jest.mock('../inputMethod');
|
||||||
|
jest.mock('../registrationUrlMethod');
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const promptsMock = jest.mocked(prompts);
|
const promptsMock = jest.mocked(prompts);
|
||||||
@@ -25,6 +29,8 @@ describe(DeviceCreateAction, () => {
|
|||||||
jest.mocked(prompts).mockImplementationOnce(async () => ({
|
jest.mocked(prompts).mockImplementationOnce(async () => ({
|
||||||
method: RegistrationMethod.WEBSITE,
|
method: RegistrationMethod.WEBSITE,
|
||||||
}));
|
}));
|
||||||
|
const appStoreApiMock = mock<AppStoreApi>();
|
||||||
|
const appStoreApi = instance(appStoreApiMock);
|
||||||
|
|
||||||
const account: Account = {
|
const account: Account = {
|
||||||
id: 'account_id',
|
id: 'account_id',
|
||||||
@@ -35,7 +41,7 @@ describe(DeviceCreateAction, () => {
|
|||||||
appleTeamIdentifier: 'ABC123Y',
|
appleTeamIdentifier: 'ABC123Y',
|
||||||
appleTeamName: 'John Doe (Individual)',
|
appleTeamName: 'John Doe (Individual)',
|
||||||
};
|
};
|
||||||
const action = new DeviceCreateAction(account, appleTeam);
|
const action = new DeviceCreateAction(appStoreApi, account, appleTeam);
|
||||||
await action.runAsync();
|
await action.runAsync();
|
||||||
|
|
||||||
expect(runRegistrationUrlMethodAsync).toBeCalled();
|
expect(runRegistrationUrlMethodAsync).toBeCalled();
|
||||||
@@ -45,6 +51,8 @@ describe(DeviceCreateAction, () => {
|
|||||||
jest.mocked(prompts).mockImplementationOnce(async () => ({
|
jest.mocked(prompts).mockImplementationOnce(async () => ({
|
||||||
method: RegistrationMethod.INPUT,
|
method: RegistrationMethod.INPUT,
|
||||||
}));
|
}));
|
||||||
|
const appStoreApiMock = mock<AppStoreApi>();
|
||||||
|
const appStoreApi = instance(appStoreApiMock);
|
||||||
|
|
||||||
const account: Account = {
|
const account: Account = {
|
||||||
id: 'account_id',
|
id: 'account_id',
|
||||||
@@ -55,10 +63,32 @@ describe(DeviceCreateAction, () => {
|
|||||||
appleTeamIdentifier: 'ABC123Y',
|
appleTeamIdentifier: 'ABC123Y',
|
||||||
appleTeamName: 'John Doe (Individual)',
|
appleTeamName: 'John Doe (Individual)',
|
||||||
};
|
};
|
||||||
const action = new DeviceCreateAction(account, appleTeam);
|
const action = new DeviceCreateAction(appStoreApi, account, appleTeam);
|
||||||
await action.runAsync();
|
await action.runAsync();
|
||||||
|
|
||||||
expect(runInputMethodAsync).toBeCalled();
|
expect(runInputMethodAsync).toBeCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('calls runDeveloperPortalMethodAsync if user chooses the developer portal method', async () => {
|
||||||
|
jest.mocked(prompts).mockImplementationOnce(async () => ({
|
||||||
|
method: RegistrationMethod.DEVELOPER_PORTAL,
|
||||||
|
}));
|
||||||
|
const appStoreApiMock = mock<AppStoreApi>();
|
||||||
|
const appStoreApi = instance(appStoreApiMock);
|
||||||
|
|
||||||
|
const account: Account = {
|
||||||
|
id: 'account_id',
|
||||||
|
name: 'foobar',
|
||||||
|
};
|
||||||
|
const appleTeam = {
|
||||||
|
id: 'apple-team-id',
|
||||||
|
appleTeamIdentifier: 'ABC123Y',
|
||||||
|
appleTeamName: 'John Doe (Individual)',
|
||||||
|
};
|
||||||
|
const action = new DeviceCreateAction(appStoreApi, account, appleTeam);
|
||||||
|
await action.runAsync();
|
||||||
|
|
||||||
|
expect(runDeveloperPortalMethodAsync).toBeCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1,20 +1,24 @@
|
|||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
|
|
||||||
|
import AppStoreApi from '../../../credentials/ios/appstore/AppStoreApi';
|
||||||
import { AppleTeam } from '../../../graphql/generated';
|
import { AppleTeam } from '../../../graphql/generated';
|
||||||
import Log from '../../../log';
|
import Log from '../../../log';
|
||||||
import { promptAsync } from '../../../prompts';
|
import { promptAsync } from '../../../prompts';
|
||||||
import { Account } from '../../../user/Account';
|
import { Account } from '../../../user/Account';
|
||||||
|
import { runDeveloperPortalMethodAsync } from './developerPortalMethod';
|
||||||
import { runInputMethodAsync } from './inputMethod';
|
import { runInputMethodAsync } from './inputMethod';
|
||||||
import { runRegistrationUrlMethodAsync } from './registrationUrlMethod';
|
import { runRegistrationUrlMethodAsync } from './registrationUrlMethod';
|
||||||
|
|
||||||
export enum RegistrationMethod {
|
export enum RegistrationMethod {
|
||||||
WEBSITE,
|
WEBSITE,
|
||||||
INPUT,
|
INPUT,
|
||||||
|
DEVELOPER_PORTAL,
|
||||||
EXIT,
|
EXIT,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class DeviceCreateAction {
|
export default class DeviceCreateAction {
|
||||||
constructor(
|
constructor(
|
||||||
|
private appStoreApi: AppStoreApi,
|
||||||
private account: Account,
|
private account: Account,
|
||||||
private appleTeam: Pick<AppleTeam, 'appleTeamIdentifier' | 'appleTeamName' | 'id'>
|
private appleTeam: Pick<AppleTeam, 'appleTeamIdentifier' | 'appleTeamName' | 'id'>
|
||||||
) {}
|
) {}
|
||||||
@@ -23,6 +27,8 @@ export default class DeviceCreateAction {
|
|||||||
const method = await this.askForRegistrationMethodAsync();
|
const method = await this.askForRegistrationMethodAsync();
|
||||||
if (method === RegistrationMethod.WEBSITE) {
|
if (method === RegistrationMethod.WEBSITE) {
|
||||||
await runRegistrationUrlMethodAsync(this.account.id, this.appleTeam);
|
await runRegistrationUrlMethodAsync(this.account.id, this.appleTeam);
|
||||||
|
} else if (method === RegistrationMethod.DEVELOPER_PORTAL) {
|
||||||
|
await runDeveloperPortalMethodAsync(this.appStoreApi, this.account.id, this.appleTeam);
|
||||||
} else if (method === RegistrationMethod.INPUT) {
|
} else if (method === RegistrationMethod.INPUT) {
|
||||||
await runInputMethodAsync(this.account.id, this.appleTeam);
|
await runInputMethodAsync(this.account.id, this.appleTeam);
|
||||||
} else if (method === RegistrationMethod.EXIT) {
|
} else if (method === RegistrationMethod.EXIT) {
|
||||||
@@ -44,6 +50,12 @@ export default class DeviceCreateAction {
|
|||||||
)} - generates a registration URL to be opened on your devices`,
|
)} - generates a registration URL to be opened on your devices`,
|
||||||
value: RegistrationMethod.WEBSITE,
|
value: RegistrationMethod.WEBSITE,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: `${chalk.bold(
|
||||||
|
'Developer Portal'
|
||||||
|
)} - import devices already registered on Apple Developer Portal`,
|
||||||
|
value: RegistrationMethod.DEVELOPER_PORTAL,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: `${chalk.bold('Input')} - allows you to type in UDIDs (advanced option)`,
|
title: `${chalk.bold('Input')} - allows you to type in UDIDs (advanced option)`,
|
||||||
value: RegistrationMethod.INPUT,
|
value: RegistrationMethod.INPUT,
|
||||||
|
|||||||
@@ -0,0 +1,131 @@
|
|||||||
|
import { Device, DeviceClass } from '@expo/apple-utils';
|
||||||
|
|
||||||
|
import { AppleDeviceMutation } from '../../../credentials/ios/api/graphql/mutations/AppleDeviceMutation';
|
||||||
|
import {
|
||||||
|
AppleDeviceFragmentWithAppleTeam,
|
||||||
|
AppleDeviceQuery,
|
||||||
|
} from '../../../credentials/ios/api/graphql/queries/AppleDeviceQuery';
|
||||||
|
import AppStoreApi from '../../../credentials/ios/appstore/AppStoreApi';
|
||||||
|
import { getRequestContext } from '../../../credentials/ios/appstore/authenticate';
|
||||||
|
import { AuthCtx } from '../../../credentials/ios/appstore/authenticateTypes';
|
||||||
|
import { AppleDeviceClass, AppleTeam } from '../../../graphql/generated';
|
||||||
|
import Log from '../../../log';
|
||||||
|
import { ora } from '../../../ora';
|
||||||
|
import { promptAsync } from '../../../prompts';
|
||||||
|
import chunk from '../../../utils/expodash/chunk';
|
||||||
|
|
||||||
|
const DEVICE_IMPORT_CHUNK_SIZE = 10;
|
||||||
|
const DEVICE_CLASS_TO_GRAPHQL_TYPE: Partial<Record<DeviceClass, AppleDeviceClass>> = {
|
||||||
|
[DeviceClass.IPAD]: AppleDeviceClass.Ipad,
|
||||||
|
[DeviceClass.IPHONE]: AppleDeviceClass.Iphone,
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function runDeveloperPortalMethodAsync(
|
||||||
|
appStoreApi: AppStoreApi,
|
||||||
|
accountId: string,
|
||||||
|
appleTeam: Pick<AppleTeam, 'appleTeamIdentifier' | 'appleTeamName' | 'id'>
|
||||||
|
): Promise<void> {
|
||||||
|
const appleAuthCtx = await appStoreApi.ensureAuthenticatedAsync();
|
||||||
|
const unregisteredPortalDevices = await findUnregisteredPortalDevicesAsync(
|
||||||
|
appleAuthCtx,
|
||||||
|
accountId,
|
||||||
|
appleTeam
|
||||||
|
);
|
||||||
|
if (unregisteredPortalDevices.length === 0) {
|
||||||
|
Log.log('All your devices registered on Apple Developer Portal are already imported to EAS.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const devicesToImport = await chooseDevicesToImportAsync(unregisteredPortalDevices);
|
||||||
|
await importDevicesAsync(accountId, appleTeam, devicesToImport);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function importDevicesAsync(
|
||||||
|
accountId: string,
|
||||||
|
appleTeam: Pick<AppleTeam, 'appleTeamIdentifier' | 'appleTeamName' | 'id'>,
|
||||||
|
devices: Device[]
|
||||||
|
): Promise<void> {
|
||||||
|
const spinner = ora(
|
||||||
|
`Importing ${devices.length} Apple device${devices.length === 1 ? '' : 's'} to EAS`
|
||||||
|
).start();
|
||||||
|
const deviceChunks = chunk(devices, DEVICE_IMPORT_CHUNK_SIZE);
|
||||||
|
try {
|
||||||
|
for (const deviceChunk of deviceChunks) {
|
||||||
|
await importDeviceChunkAsync(accountId, appleTeam, deviceChunk);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
spinner.fail();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
spinner.succeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function importDeviceChunkAsync(
|
||||||
|
accountId: string,
|
||||||
|
appleTeam: Pick<AppleTeam, 'appleTeamIdentifier' | 'appleTeamName' | 'id'>,
|
||||||
|
devices: Device[]
|
||||||
|
): Promise<void> {
|
||||||
|
const promises = devices.map(device => {
|
||||||
|
return AppleDeviceMutation.createAppleDeviceAsync(
|
||||||
|
{
|
||||||
|
appleTeamId: appleTeam.id,
|
||||||
|
identifier: device.attributes.udid,
|
||||||
|
name: device.attributes.name,
|
||||||
|
deviceClass: DEVICE_CLASS_TO_GRAPHQL_TYPE[device.attributes.deviceClass] ?? undefined,
|
||||||
|
},
|
||||||
|
accountId
|
||||||
|
);
|
||||||
|
});
|
||||||
|
await Promise.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function findUnregisteredPortalDevicesAsync(
|
||||||
|
appleAuthCtx: AuthCtx,
|
||||||
|
accountId: string,
|
||||||
|
appleTeam: Pick<AppleTeam, 'appleTeamIdentifier' | 'appleTeamName' | 'id'>
|
||||||
|
): Promise<Device[]> {
|
||||||
|
const expoRegisteredDevices = await AppleDeviceQuery.getAllByAppleTeamIdentifierAsync(
|
||||||
|
accountId,
|
||||||
|
appleTeam.appleTeamIdentifier,
|
||||||
|
{ useCache: false }
|
||||||
|
);
|
||||||
|
const expoRegisteredDevicesByUdid = expoRegisteredDevices.reduce((acc, device) => {
|
||||||
|
acc[device.identifier] = device;
|
||||||
|
return acc;
|
||||||
|
}, {} as Record<string, AppleDeviceFragmentWithAppleTeam>);
|
||||||
|
|
||||||
|
const portalDevices = await Device.getAllIOSProfileDevicesAsync(getRequestContext(appleAuthCtx));
|
||||||
|
return portalDevices.filter(
|
||||||
|
portalDevice =>
|
||||||
|
!(portalDevice.attributes.udid in expoRegisteredDevicesByUdid) &&
|
||||||
|
[DeviceClass.IPAD, DeviceClass.IPHONE].includes(portalDevice.attributes.deviceClass)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function chooseDevicesToImportAsync(devices: Device[]): Promise<Device[]> {
|
||||||
|
const { chosenDevices } = await promptAsync({
|
||||||
|
type: 'multiselect',
|
||||||
|
name: 'chosenDevices',
|
||||||
|
message: 'Which devices do you want to import to EAS?',
|
||||||
|
choices: devices.map(device => ({
|
||||||
|
value: device,
|
||||||
|
title: formatDeviceLabel(device),
|
||||||
|
selected: true,
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
return chosenDevices;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatDeviceLabel(device: Device): string {
|
||||||
|
const deviceDetails = formatDeviceDetails(device);
|
||||||
|
return `${device.attributes.name} - ${device.attributes.udid})${
|
||||||
|
deviceDetails !== '' ? ` - ${deviceDetails}` : ''
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDeviceDetails(device: Device): string {
|
||||||
|
let details: string = device.attributes.deviceClass;
|
||||||
|
if (device.attributes.model) {
|
||||||
|
details = device.attributes.model;
|
||||||
|
}
|
||||||
|
return details === '' ? details : `(${details})`;
|
||||||
|
}
|
||||||
@@ -29,12 +29,12 @@ export default class DeviceManager {
|
|||||||
Log.addNewLineIfNone();
|
Log.addNewLineIfNone();
|
||||||
|
|
||||||
const account = await this.resolveAccountAsync();
|
const account = await this.resolveAccountAsync();
|
||||||
const { team } = await this.ctx.appStore.ensureAuthenticatedAsync();
|
const appleAuthCtx = await this.ctx.appStore.ensureAuthenticatedAsync();
|
||||||
const appleTeam = await ensureAppleTeamExistsAsync(account.id, {
|
const appleTeam = await ensureAppleTeamExistsAsync(account.id, {
|
||||||
appleTeamIdentifier: team.id,
|
appleTeamIdentifier: appleAuthCtx.team.id,
|
||||||
appleTeamName: team.name,
|
appleTeamName: appleAuthCtx.team.name,
|
||||||
});
|
});
|
||||||
const action = new DeviceCreateAction(account, appleTeam);
|
const action = new DeviceCreateAction(this.ctx.appStore, account, appleTeam);
|
||||||
await action.runAsync();
|
await action.runAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export default {
|
||||||
|
/**
|
||||||
|
* Dangerous overrides, use only if you know what you are doing
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides applicationId from Android project, setting this option will also
|
||||||
|
* ignore failures when parsing build.gradle.
|
||||||
|
*/
|
||||||
|
overrideAndroidApplicationId: process.env.EAS_DANGEROUS_OVERRIDE_ANDROID_APPLICATION_ID,
|
||||||
|
};
|
||||||
+325
-31
@@ -94,7 +94,7 @@ export type Account = {
|
|||||||
apps: Array<App>;
|
apps: Array<App>;
|
||||||
/** @deprecated Build packs are no longer supported */
|
/** @deprecated Build packs are no longer supported */
|
||||||
availableBuilds?: Maybe<Scalars['Int']>;
|
availableBuilds?: Maybe<Scalars['Int']>;
|
||||||
/** Billing information */
|
/** Billing information. Only visible to members with the ADMIN or OWNER role. */
|
||||||
billing?: Maybe<Billing>;
|
billing?: Maybe<Billing>;
|
||||||
billingPeriod: BillingPeriod;
|
billingPeriod: BillingPeriod;
|
||||||
/** Build Jobs associated with this account */
|
/** Build Jobs associated with this account */
|
||||||
@@ -123,6 +123,8 @@ export type Account = {
|
|||||||
requiresAccessTokenForPushSecurity: Scalars['Boolean'];
|
requiresAccessTokenForPushSecurity: Scalars['Boolean'];
|
||||||
/** Snacks associated with this account */
|
/** Snacks associated with this account */
|
||||||
snacks: Array<Snack>;
|
snacks: Array<Snack>;
|
||||||
|
/** SSO configuration for this account */
|
||||||
|
ssoConfiguration?: Maybe<AccountSsoConfiguration>;
|
||||||
/** Subscription info visible to members that have VIEWER role */
|
/** Subscription info visible to members that have VIEWER role */
|
||||||
subscription?: Maybe<SubscriptionDetails>;
|
subscription?: Maybe<SubscriptionDetails>;
|
||||||
/** @deprecated No longer needed */
|
/** @deprecated No longer needed */
|
||||||
@@ -338,7 +340,9 @@ export type AccountMutationRenameArgs = {
|
|||||||
|
|
||||||
export type AccountMutationRequestRefundArgs = {
|
export type AccountMutationRequestRefundArgs = {
|
||||||
accountID: Scalars['ID'];
|
accountID: Scalars['ID'];
|
||||||
chargeIdentifier: Scalars['ID'];
|
chargeID: Scalars['ID'];
|
||||||
|
description?: InputMaybe<Scalars['String']>;
|
||||||
|
reason?: InputMaybe<Scalars['String']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -391,23 +395,127 @@ export type AccountQueryByNameArgs = {
|
|||||||
accountName: Scalars['String'];
|
accountName: Scalars['String'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Auth configuration data for an SSO account. */
|
||||||
|
export type AccountSsoConfiguration = {
|
||||||
|
__typename?: 'AccountSSOConfiguration';
|
||||||
|
authEndpoint?: Maybe<Scalars['String']>;
|
||||||
|
authProtocol: AuthProtocolType;
|
||||||
|
authProviderIdentifier: Scalars['String'];
|
||||||
|
clientIdentifier: Scalars['String'];
|
||||||
|
clientSecret: Scalars['String'];
|
||||||
|
createdAt: Scalars['DateTime'];
|
||||||
|
id: Scalars['ID'];
|
||||||
|
issuer?: Maybe<Scalars['String']>;
|
||||||
|
jwksEndpoint?: Maybe<Scalars['String']>;
|
||||||
|
redirectUri: Scalars['String'];
|
||||||
|
tokenEndpoint?: Maybe<Scalars['String']>;
|
||||||
|
updatedAt: Scalars['DateTime'];
|
||||||
|
userInfoEndpoint?: Maybe<Scalars['String']>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AccountSsoConfigurationData = {
|
||||||
|
authEndpoint?: InputMaybe<Scalars['String']>;
|
||||||
|
authProtocol: AuthProtocolType;
|
||||||
|
authProviderIdentifier: Scalars['String'];
|
||||||
|
clientIdentifier: Scalars['String'];
|
||||||
|
clientSecret: Scalars['String'];
|
||||||
|
issuer?: InputMaybe<Scalars['String']>;
|
||||||
|
jwksEndpoint?: InputMaybe<Scalars['String']>;
|
||||||
|
redirectUri: Scalars['String'];
|
||||||
|
tokenEndpoint?: InputMaybe<Scalars['String']>;
|
||||||
|
userInfoEndpoint?: InputMaybe<Scalars['String']>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AccountSsoConfigurationMutation = {
|
||||||
|
__typename?: 'AccountSSOConfigurationMutation';
|
||||||
|
/** Create an AccountSSOConfiguration for an Account */
|
||||||
|
createAccountSSOConfiguration: AccountSsoConfiguration;
|
||||||
|
/** Delete an AccountSSOConfiguration */
|
||||||
|
deleteAccountSSOConfiguration: DeleteAccountSsoConfigurationResult;
|
||||||
|
/** Update an AccountSSOConfiguration */
|
||||||
|
updateAccountSSOConfiguration: AccountSsoConfiguration;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type AccountSsoConfigurationMutationCreateAccountSsoConfigurationArgs = {
|
||||||
|
accountId: Scalars['ID'];
|
||||||
|
accountSSOConfigurationData: AccountSsoConfigurationData;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type AccountSsoConfigurationMutationDeleteAccountSsoConfigurationArgs = {
|
||||||
|
id: Scalars['ID'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type AccountSsoConfigurationMutationUpdateAccountSsoConfigurationArgs = {
|
||||||
|
accountSSOConfigurationData: AccountSsoConfigurationData;
|
||||||
|
id: Scalars['ID'];
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Public auth configuration data for an SSO account. */
|
||||||
|
export type AccountSsoConfigurationPublicData = {
|
||||||
|
__typename?: 'AccountSSOConfigurationPublicData';
|
||||||
|
authEndpoint?: Maybe<Scalars['String']>;
|
||||||
|
authProtocol: AuthProtocolType;
|
||||||
|
authProviderIdentifier: Scalars['String'];
|
||||||
|
clientIdentifier: Scalars['String'];
|
||||||
|
id: Scalars['ID'];
|
||||||
|
issuer?: Maybe<Scalars['String']>;
|
||||||
|
jwksEndpoint?: Maybe<Scalars['String']>;
|
||||||
|
redirectUri: Scalars['String'];
|
||||||
|
tokenEndpoint?: Maybe<Scalars['String']>;
|
||||||
|
userInfoEndpoint?: Maybe<Scalars['String']>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AccountSsoConfigurationPublicDataQuery = {
|
||||||
|
__typename?: 'AccountSSOConfigurationPublicDataQuery';
|
||||||
|
/** Get AccountSSOConfiguration public data by account name */
|
||||||
|
publicDataByAccountName: AccountSsoConfigurationPublicData;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type AccountSsoConfigurationPublicDataQueryPublicDataByAccountNameArgs = {
|
||||||
|
accountName: Scalars['String'];
|
||||||
|
};
|
||||||
|
|
||||||
export type AccountUsageMetric = {
|
export type AccountUsageMetric = {
|
||||||
__typename?: 'AccountUsageMetric';
|
__typename?: 'AccountUsageMetric';
|
||||||
metric: EasServiceMetric;
|
id: Scalars['ID'];
|
||||||
metricType: UsageMetricType;
|
metricType: UsageMetricType;
|
||||||
|
serviceMetric: EasServiceMetric;
|
||||||
timestamp: Scalars['DateTime'];
|
timestamp: Scalars['DateTime'];
|
||||||
value: Scalars['Float'];
|
value: Scalars['Float'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type AccountUsageMetricAndCost = {
|
||||||
|
__typename?: 'AccountUsageMetricAndCost';
|
||||||
|
id: Scalars['ID'];
|
||||||
|
/** The limit, in units, allowed by this plan */
|
||||||
|
limit: Scalars['Float'];
|
||||||
|
metricType: UsageMetricType;
|
||||||
|
serviceMetric: EasServiceMetric;
|
||||||
|
/** Total cost of this particular metric, in cents */
|
||||||
|
totalCost: Scalars['Float'];
|
||||||
|
value: Scalars['Float'];
|
||||||
|
};
|
||||||
|
|
||||||
export type AccountUsageMetrics = {
|
export type AccountUsageMetrics = {
|
||||||
__typename?: 'AccountUsageMetrics';
|
__typename?: 'AccountUsageMetrics';
|
||||||
|
byBillingPeriod: UsageMetricTotal;
|
||||||
metricsForServiceMetric: Array<AccountUsageMetric>;
|
metricsForServiceMetric: Array<AccountUsageMetric>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type AccountUsageMetricsByBillingPeriodArgs = {
|
||||||
|
date: Scalars['DateTime'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export type AccountUsageMetricsMetricsForServiceMetricArgs = {
|
export type AccountUsageMetricsMetricsForServiceMetricArgs = {
|
||||||
|
filterParams?: InputMaybe<Scalars['JSONObject']>;
|
||||||
granularity: UsageMetricsGranularity;
|
granularity: UsageMetricsGranularity;
|
||||||
metric: EasServiceMetric;
|
serviceMetric: EasServiceMetric;
|
||||||
timespan: UsageMetricsTimespan;
|
timespan: UsageMetricsTimespan;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -687,6 +795,7 @@ export type AndroidJobInput = {
|
|||||||
type: BuildWorkflow;
|
type: BuildWorkflow;
|
||||||
updates?: InputMaybe<BuildUpdatesInput>;
|
updates?: InputMaybe<BuildUpdatesInput>;
|
||||||
username?: InputMaybe<Scalars['String']>;
|
username?: InputMaybe<Scalars['String']>;
|
||||||
|
version?: InputMaybe<AndroidJobVersionInput>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AndroidJobKeystoreInput = {
|
export type AndroidJobKeystoreInput = {
|
||||||
@@ -701,6 +810,10 @@ export type AndroidJobSecretsInput = {
|
|||||||
environmentSecrets?: InputMaybe<Scalars['JSONObject']>;
|
environmentSecrets?: InputMaybe<Scalars['JSONObject']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type AndroidJobVersionInput = {
|
||||||
|
versionCode: Scalars['String'];
|
||||||
|
};
|
||||||
|
|
||||||
export type AndroidKeystore = {
|
export type AndroidKeystore = {
|
||||||
__typename?: 'AndroidKeystore';
|
__typename?: 'AndroidKeystore';
|
||||||
account: Account;
|
account: Account;
|
||||||
@@ -813,6 +926,7 @@ export type App = Project & {
|
|||||||
isLikedByMe: Scalars['Boolean'];
|
isLikedByMe: Scalars['Boolean'];
|
||||||
/** @deprecated No longer supported */
|
/** @deprecated No longer supported */
|
||||||
lastPublishedTime: Scalars['DateTime'];
|
lastPublishedTime: Scalars['DateTime'];
|
||||||
|
latestAppVersionByPlatformAndApplicationIdentifier?: Maybe<AppVersion>;
|
||||||
latestReleaseForReleaseChannel?: Maybe<AppRelease>;
|
latestReleaseForReleaseChannel?: Maybe<AppRelease>;
|
||||||
/** ID of latest classic update release */
|
/** ID of latest classic update release */
|
||||||
latestReleaseId: Scalars['ID'];
|
latestReleaseId: Scalars['ID'];
|
||||||
@@ -935,6 +1049,13 @@ export type AppIosAppCredentialsArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Represents an Exponent App (or Experience in legacy terms) */
|
||||||
|
export type AppLatestAppVersionByPlatformAndApplicationIdentifierArgs = {
|
||||||
|
applicationIdentifier: Scalars['String'];
|
||||||
|
platform: AppPlatform;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/** Represents an Exponent App (or Experience in legacy terms) */
|
/** Represents an Exponent App (or Experience in legacy terms) */
|
||||||
export type AppLatestReleaseForReleaseChannelArgs = {
|
export type AppLatestReleaseForReleaseChannelArgs = {
|
||||||
platform: AppPlatform;
|
platform: AppPlatform;
|
||||||
@@ -1002,15 +1123,20 @@ export type AppDataInput = {
|
|||||||
|
|
||||||
export type AppIcon = {
|
export type AppIcon = {
|
||||||
__typename?: 'AppIcon';
|
__typename?: 'AppIcon';
|
||||||
/** Nullable color palette of the app icon. If null, color palette couldn't be retrieved from external service (imgix) */
|
/** @deprecated No longer supported */
|
||||||
colorPalette?: Maybe<Scalars['JSON']>;
|
colorPalette?: Maybe<Scalars['JSON']>;
|
||||||
originalUrl: Scalars['String'];
|
originalUrl: Scalars['String'];
|
||||||
primaryColor?: Maybe<Scalars['String']>;
|
primaryColor?: Maybe<Scalars['String']>;
|
||||||
url: Scalars['String'];
|
url: Scalars['String'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type AppInfoInput = {
|
||||||
|
displayName?: InputMaybe<Scalars['String']>;
|
||||||
|
};
|
||||||
|
|
||||||
export type AppInput = {
|
export type AppInput = {
|
||||||
accountId: Scalars['ID'];
|
accountId: Scalars['ID'];
|
||||||
|
appInfo?: InputMaybe<AppInfoInput>;
|
||||||
privacy: AppPrivacy;
|
privacy: AppPrivacy;
|
||||||
projectName: Scalars['String'];
|
projectName: Scalars['String'];
|
||||||
};
|
};
|
||||||
@@ -1021,6 +1147,8 @@ export type AppMutation = {
|
|||||||
createApp: App;
|
createApp: App;
|
||||||
/** @deprecated No longer supported */
|
/** @deprecated No longer supported */
|
||||||
grantAccess?: Maybe<App>;
|
grantAccess?: Maybe<App>;
|
||||||
|
/** Set display info for app */
|
||||||
|
setAppInfo: App;
|
||||||
/** Require api token to send push notifs for experience */
|
/** Require api token to send push notifs for experience */
|
||||||
setPushSecurityEnabled: App;
|
setPushSecurityEnabled: App;
|
||||||
};
|
};
|
||||||
@@ -1037,6 +1165,12 @@ export type AppMutationGrantAccessArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type AppMutationSetAppInfoArgs = {
|
||||||
|
appId: Scalars['ID'];
|
||||||
|
appInfo: AppInfoInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export type AppMutationSetPushSecurityEnabledArgs = {
|
export type AppMutationSetPushSecurityEnabledArgs = {
|
||||||
appId: Scalars['ID'];
|
appId: Scalars['ID'];
|
||||||
pushSecurityEnabled: Scalars['Boolean'];
|
pushSecurityEnabled: Scalars['Boolean'];
|
||||||
@@ -1164,6 +1298,52 @@ export enum AppStoreConnectUserRole {
|
|||||||
Unknown = 'UNKNOWN'
|
Unknown = 'UNKNOWN'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Represents Play Store/App Store version of an application */
|
||||||
|
export type AppVersion = {
|
||||||
|
__typename?: 'AppVersion';
|
||||||
|
/**
|
||||||
|
* Store identifier for an application
|
||||||
|
* - Android - applicationId
|
||||||
|
* - iOS - bundle identifier
|
||||||
|
*/
|
||||||
|
applicationIdentifier: Scalars['String'];
|
||||||
|
/**
|
||||||
|
* Value that identifies build in a store (it's visible to developers, but not to end users)
|
||||||
|
* - Android - versionCode in build.gradle ("android.versionCode" field in app.json)
|
||||||
|
* - iOS - CFBundleVersion in Info.plist ("ios.buildNumber" field in app.json)
|
||||||
|
*/
|
||||||
|
buildVersion: Scalars['String'];
|
||||||
|
id: Scalars['ID'];
|
||||||
|
platform: AppPlatform;
|
||||||
|
runtimeVersion?: Maybe<Scalars['String']>;
|
||||||
|
/**
|
||||||
|
* User-facing version in a store
|
||||||
|
* - Android - versionName in build.gradle ("version" field in app.json)
|
||||||
|
* - iOS - CFBundleShortVersionString in Info.plist ("version" field in app.json)
|
||||||
|
*/
|
||||||
|
storeVersion: Scalars['String'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AppVersionInput = {
|
||||||
|
appId: Scalars['ID'];
|
||||||
|
applicationIdentifier: Scalars['String'];
|
||||||
|
buildVersion: Scalars['String'];
|
||||||
|
platform: AppPlatform;
|
||||||
|
runtimeVersion?: InputMaybe<Scalars['String']>;
|
||||||
|
storeVersion: Scalars['String'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AppVersionMutation = {
|
||||||
|
__typename?: 'AppVersionMutation';
|
||||||
|
/** Create an app version */
|
||||||
|
createAppVersion: AppVersion;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type AppVersionMutationCreateAppVersionArgs = {
|
||||||
|
appVersionInput: AppVersionInput;
|
||||||
|
};
|
||||||
|
|
||||||
export type AppleAppIdentifier = {
|
export type AppleAppIdentifier = {
|
||||||
__typename?: 'AppleAppIdentifier';
|
__typename?: 'AppleAppIdentifier';
|
||||||
account: Account;
|
account: Account;
|
||||||
@@ -1380,7 +1560,7 @@ export type ApplePushKey = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type ApplePushKeyInput = {
|
export type ApplePushKeyInput = {
|
||||||
appleTeamId?: InputMaybe<Scalars['ID']>;
|
appleTeamId: Scalars['ID'];
|
||||||
keyIdentifier: Scalars['String'];
|
keyIdentifier: Scalars['String'];
|
||||||
keyP8: Scalars['String'];
|
keyP8: Scalars['String'];
|
||||||
};
|
};
|
||||||
@@ -1505,6 +1685,10 @@ export type AssetQueryMetadataArgs = {
|
|||||||
storageKeys: Array<Scalars['String']>;
|
storageKeys: Array<Scalars['String']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export enum AuthProtocolType {
|
||||||
|
Oidc = 'OIDC'
|
||||||
|
}
|
||||||
|
|
||||||
export type Billing = {
|
export type Billing = {
|
||||||
__typename?: 'Billing';
|
__typename?: 'Billing';
|
||||||
/** History of invoices */
|
/** History of invoices */
|
||||||
@@ -1530,10 +1714,14 @@ export type Build = ActivityTimelineProjectActivity & BuildOrBuildJob & {
|
|||||||
appVersion?: Maybe<Scalars['String']>;
|
appVersion?: Maybe<Scalars['String']>;
|
||||||
artifacts?: Maybe<BuildArtifacts>;
|
artifacts?: Maybe<BuildArtifacts>;
|
||||||
buildProfile?: Maybe<Scalars['String']>;
|
buildProfile?: Maybe<Scalars['String']>;
|
||||||
|
canRetry: Scalars['Boolean'];
|
||||||
cancelingActor?: Maybe<Actor>;
|
cancelingActor?: Maybe<Actor>;
|
||||||
channel?: Maybe<Scalars['String']>;
|
channel?: Maybe<Scalars['String']>;
|
||||||
createdAt?: Maybe<Scalars['DateTime']>;
|
childBuild?: Maybe<Build>;
|
||||||
|
completedAt?: Maybe<Scalars['DateTime']>;
|
||||||
|
createdAt: Scalars['DateTime'];
|
||||||
distribution?: Maybe<DistributionType>;
|
distribution?: Maybe<DistributionType>;
|
||||||
|
enqueuedAt?: Maybe<Scalars['DateTime']>;
|
||||||
error?: Maybe<BuildError>;
|
error?: Maybe<BuildError>;
|
||||||
estimatedWaitTimeLeftSeconds?: Maybe<Scalars['Int']>;
|
estimatedWaitTimeLeftSeconds?: Maybe<Scalars['Int']>;
|
||||||
expirationDate?: Maybe<Scalars['DateTime']>;
|
expirationDate?: Maybe<Scalars['DateTime']>;
|
||||||
@@ -1547,19 +1735,27 @@ export type Build = ActivityTimelineProjectActivity & BuildOrBuildJob & {
|
|||||||
iosEnterpriseProvisioning?: Maybe<BuildIosEnterpriseProvisioning>;
|
iosEnterpriseProvisioning?: Maybe<BuildIosEnterpriseProvisioning>;
|
||||||
isGitWorkingTreeDirty?: Maybe<Scalars['Boolean']>;
|
isGitWorkingTreeDirty?: Maybe<Scalars['Boolean']>;
|
||||||
logFiles: Array<Scalars['String']>;
|
logFiles: Array<Scalars['String']>;
|
||||||
|
maxBuildTimeSeconds: Scalars['Int'];
|
||||||
|
/** Retry time starts after completedAt */
|
||||||
|
maxRetryTimeMinutes: Scalars['Int'];
|
||||||
|
message?: Maybe<Scalars['String']>;
|
||||||
metrics?: Maybe<BuildMetrics>;
|
metrics?: Maybe<BuildMetrics>;
|
||||||
|
parentBuild?: Maybe<Build>;
|
||||||
platform: AppPlatform;
|
platform: AppPlatform;
|
||||||
priority: BuildPriority;
|
priority: BuildPriority;
|
||||||
project: Project;
|
project: Project;
|
||||||
|
provisioningStartedAt?: Maybe<Scalars['DateTime']>;
|
||||||
/** Queue position is 1-indexed */
|
/** Queue position is 1-indexed */
|
||||||
queuePosition?: Maybe<Scalars['Int']>;
|
queuePosition?: Maybe<Scalars['Int']>;
|
||||||
reactNativeVersion?: Maybe<Scalars['String']>;
|
reactNativeVersion?: Maybe<Scalars['String']>;
|
||||||
releaseChannel?: Maybe<Scalars['String']>;
|
releaseChannel?: Maybe<Scalars['String']>;
|
||||||
|
resourceClass?: Maybe<BuildResourceClass>;
|
||||||
runtimeVersion?: Maybe<Scalars['String']>;
|
runtimeVersion?: Maybe<Scalars['String']>;
|
||||||
sdkVersion?: Maybe<Scalars['String']>;
|
sdkVersion?: Maybe<Scalars['String']>;
|
||||||
status: BuildStatus;
|
status: BuildStatus;
|
||||||
submissions: Array<Submission>;
|
submissions: Array<Submission>;
|
||||||
updatedAt?: Maybe<Scalars['DateTime']>;
|
updatedAt: Scalars['DateTime'];
|
||||||
|
workerStartedAt?: Maybe<Scalars['DateTime']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type BuildArtifact = {
|
export type BuildArtifact = {
|
||||||
@@ -1700,6 +1896,7 @@ export type BuildMetadataInput = {
|
|||||||
gitCommitHash?: InputMaybe<Scalars['String']>;
|
gitCommitHash?: InputMaybe<Scalars['String']>;
|
||||||
iosEnterpriseProvisioning?: InputMaybe<BuildIosEnterpriseProvisioning>;
|
iosEnterpriseProvisioning?: InputMaybe<BuildIosEnterpriseProvisioning>;
|
||||||
isGitWorkingTreeDirty?: InputMaybe<Scalars['Boolean']>;
|
isGitWorkingTreeDirty?: InputMaybe<Scalars['Boolean']>;
|
||||||
|
message?: InputMaybe<Scalars['String']>;
|
||||||
reactNativeVersion?: InputMaybe<Scalars['String']>;
|
reactNativeVersion?: InputMaybe<Scalars['String']>;
|
||||||
releaseChannel?: InputMaybe<Scalars['String']>;
|
releaseChannel?: InputMaybe<Scalars['String']>;
|
||||||
runtimeVersion?: InputMaybe<Scalars['String']>;
|
runtimeVersion?: InputMaybe<Scalars['String']>;
|
||||||
@@ -1731,6 +1928,8 @@ export type BuildMutation = {
|
|||||||
createIosBuild: CreateBuildResult;
|
createIosBuild: CreateBuildResult;
|
||||||
/** Delete an EAS Build build */
|
/** Delete an EAS Build build */
|
||||||
deleteBuild: Build;
|
deleteBuild: Build;
|
||||||
|
/** Retry an EAS Build build */
|
||||||
|
retryBuild: Build;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -1741,6 +1940,7 @@ export type BuildMutationCancelBuildArgs = {
|
|||||||
|
|
||||||
export type BuildMutationCreateAndroidBuildArgs = {
|
export type BuildMutationCreateAndroidBuildArgs = {
|
||||||
appId: Scalars['ID'];
|
appId: Scalars['ID'];
|
||||||
|
buildParams?: InputMaybe<BuildParamsInput>;
|
||||||
job: AndroidJobInput;
|
job: AndroidJobInput;
|
||||||
metadata?: InputMaybe<BuildMetadataInput>;
|
metadata?: InputMaybe<BuildMetadataInput>;
|
||||||
};
|
};
|
||||||
@@ -1748,6 +1948,7 @@ export type BuildMutationCreateAndroidBuildArgs = {
|
|||||||
|
|
||||||
export type BuildMutationCreateIosBuildArgs = {
|
export type BuildMutationCreateIosBuildArgs = {
|
||||||
appId: Scalars['ID'];
|
appId: Scalars['ID'];
|
||||||
|
buildParams?: InputMaybe<BuildParamsInput>;
|
||||||
job: IosJobInput;
|
job: IosJobInput;
|
||||||
metadata?: InputMaybe<BuildMetadataInput>;
|
metadata?: InputMaybe<BuildMetadataInput>;
|
||||||
};
|
};
|
||||||
@@ -1757,13 +1958,23 @@ export type BuildMutationDeleteBuildArgs = {
|
|||||||
buildId: Scalars['ID'];
|
buildId: Scalars['ID'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type BuildMutationRetryBuildArgs = {
|
||||||
|
buildId: Scalars['ID'];
|
||||||
|
};
|
||||||
|
|
||||||
export type BuildOrBuildJob = {
|
export type BuildOrBuildJob = {
|
||||||
id: Scalars['ID'];
|
id: Scalars['ID'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type BuildParamsInput = {
|
||||||
|
resourceClass: BuildResourceClass;
|
||||||
|
};
|
||||||
|
|
||||||
export enum BuildPriority {
|
export enum BuildPriority {
|
||||||
High = 'HIGH',
|
High = 'HIGH',
|
||||||
Normal = 'NORMAL'
|
Normal = 'NORMAL',
|
||||||
|
NormalPlus = 'NORMAL_PLUS'
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Publicly visible data for a Build. */
|
/** Publicly visible data for a Build. */
|
||||||
@@ -1828,6 +2039,14 @@ export type BuildQueryByIdArgs = {
|
|||||||
buildId: Scalars['ID'];
|
buildId: Scalars['ID'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export enum BuildResourceClass {
|
||||||
|
AndroidDefault = 'ANDROID_DEFAULT',
|
||||||
|
AndroidLarge = 'ANDROID_LARGE',
|
||||||
|
IosDefault = 'IOS_DEFAULT',
|
||||||
|
IosLarge = 'IOS_LARGE',
|
||||||
|
Legacy = 'LEGACY'
|
||||||
|
}
|
||||||
|
|
||||||
export enum BuildStatus {
|
export enum BuildStatus {
|
||||||
Canceled = 'CANCELED',
|
Canceled = 'CANCELED',
|
||||||
Errored = 'ERRORED',
|
Errored = 'ERRORED',
|
||||||
@@ -1905,6 +2124,13 @@ export type CodeSigningInfoInput = {
|
|||||||
sig: Scalars['String'];
|
sig: Scalars['String'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type Concurrencies = {
|
||||||
|
__typename?: 'Concurrencies';
|
||||||
|
android: Scalars['Int'];
|
||||||
|
ios: Scalars['Int'];
|
||||||
|
total: Scalars['Int'];
|
||||||
|
};
|
||||||
|
|
||||||
export type CreateAccessTokenInput = {
|
export type CreateAccessTokenInput = {
|
||||||
actorID: Scalars['ID'];
|
actorID: Scalars['ID'];
|
||||||
note?: InputMaybe<Scalars['String']>;
|
note?: InputMaybe<Scalars['String']>;
|
||||||
@@ -1920,6 +2146,7 @@ export type CreateAccessTokenResponse = {
|
|||||||
|
|
||||||
export type CreateAndroidSubmissionInput = {
|
export type CreateAndroidSubmissionInput = {
|
||||||
appId: Scalars['ID'];
|
appId: Scalars['ID'];
|
||||||
|
archiveUrl?: InputMaybe<Scalars['String']>;
|
||||||
config: AndroidSubmissionConfigInput;
|
config: AndroidSubmissionConfigInput;
|
||||||
submittedBuildId?: InputMaybe<Scalars['ID']>;
|
submittedBuildId?: InputMaybe<Scalars['ID']>;
|
||||||
};
|
};
|
||||||
@@ -1937,17 +2164,11 @@ export type CreateEnvironmentSecretInput = {
|
|||||||
|
|
||||||
export type CreateIosSubmissionInput = {
|
export type CreateIosSubmissionInput = {
|
||||||
appId: Scalars['ID'];
|
appId: Scalars['ID'];
|
||||||
|
archiveUrl?: InputMaybe<Scalars['String']>;
|
||||||
config: IosSubmissionConfigInput;
|
config: IosSubmissionConfigInput;
|
||||||
submittedBuildId?: InputMaybe<Scalars['ID']>;
|
submittedBuildId?: InputMaybe<Scalars['ID']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CreateSubmissionInput = {
|
|
||||||
appId: Scalars['ID'];
|
|
||||||
config: Scalars['JSONObject'];
|
|
||||||
platform: AppPlatform;
|
|
||||||
submittedBuildId?: InputMaybe<Scalars['ID']>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type CreateSubmissionResult = {
|
export type CreateSubmissionResult = {
|
||||||
__typename?: 'CreateSubmissionResult';
|
__typename?: 'CreateSubmissionResult';
|
||||||
/** Created submission */
|
/** Created submission */
|
||||||
@@ -1964,6 +2185,11 @@ export type DeleteAccountResult = {
|
|||||||
id: Scalars['ID'];
|
id: Scalars['ID'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type DeleteAccountSsoConfigurationResult = {
|
||||||
|
__typename?: 'DeleteAccountSSOConfigurationResult';
|
||||||
|
id: Scalars['ID'];
|
||||||
|
};
|
||||||
|
|
||||||
export type DeleteAndroidKeystoreResult = {
|
export type DeleteAndroidKeystoreResult = {
|
||||||
__typename?: 'DeleteAndroidKeystoreResult';
|
__typename?: 'DeleteAndroidKeystoreResult';
|
||||||
id: Scalars['ID'];
|
id: Scalars['ID'];
|
||||||
@@ -2057,7 +2283,11 @@ export enum EasBuildDeprecationInfoType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum EasServiceMetric {
|
export enum EasServiceMetric {
|
||||||
ManifestRequests = 'MANIFEST_REQUESTS'
|
AssetsRequests = 'ASSETS_REQUESTS',
|
||||||
|
BandwidthUsage = 'BANDWIDTH_USAGE',
|
||||||
|
Builds = 'BUILDS',
|
||||||
|
ManifestRequests = 'MANIFEST_REQUESTS',
|
||||||
|
UniqueUsers = 'UNIQUE_USERS'
|
||||||
}
|
}
|
||||||
|
|
||||||
export type EditUpdateBranchInput = {
|
export type EditUpdateBranchInput = {
|
||||||
@@ -2149,6 +2379,15 @@ export enum Feature {
|
|||||||
Teams = 'TEAMS'
|
Teams = 'TEAMS'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type FutureSubscription = {
|
||||||
|
__typename?: 'FutureSubscription';
|
||||||
|
createdAt: Scalars['DateTime'];
|
||||||
|
id: Scalars['ID'];
|
||||||
|
meteredBillingStatus: MeteredBillingStatus;
|
||||||
|
planId: Scalars['String'];
|
||||||
|
startDate: Scalars['DateTime'];
|
||||||
|
};
|
||||||
|
|
||||||
export type GetSignedAssetUploadSpecificationsResult = {
|
export type GetSignedAssetUploadSpecificationsResult = {
|
||||||
__typename?: 'GetSignedAssetUploadSpecificationsResult';
|
__typename?: 'GetSignedAssetUploadSpecificationsResult';
|
||||||
specifications: Array<Scalars['String']>;
|
specifications: Array<Scalars['String']>;
|
||||||
@@ -2421,6 +2660,7 @@ export type IosJobInput = {
|
|||||||
type: BuildWorkflow;
|
type: BuildWorkflow;
|
||||||
updates?: InputMaybe<BuildUpdatesInput>;
|
updates?: InputMaybe<BuildUpdatesInput>;
|
||||||
username?: InputMaybe<Scalars['String']>;
|
username?: InputMaybe<Scalars['String']>;
|
||||||
|
version?: InputMaybe<IosJobVersionInput>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type IosJobSecretsInput = {
|
export type IosJobSecretsInput = {
|
||||||
@@ -2434,6 +2674,10 @@ export type IosJobTargetCredentialsInput = {
|
|||||||
targetName: Scalars['String'];
|
targetName: Scalars['String'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type IosJobVersionInput = {
|
||||||
|
buildNumber: Scalars['String'];
|
||||||
|
};
|
||||||
|
|
||||||
/** @deprecated Use developmentClient option instead. */
|
/** @deprecated Use developmentClient option instead. */
|
||||||
export enum IosManagedBuildType {
|
export enum IosManagedBuildType {
|
||||||
DevelopmentClient = 'DEVELOPMENT_CLIENT',
|
DevelopmentClient = 'DEVELOPMENT_CLIENT',
|
||||||
@@ -2615,6 +2859,11 @@ export type MeMutationUpdateProfileArgs = {
|
|||||||
userData: UserDataInput;
|
userData: UserDataInput;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type MeteredBillingStatus = {
|
||||||
|
__typename?: 'MeteredBillingStatus';
|
||||||
|
EAS_UPDATE: Scalars['Boolean'];
|
||||||
|
};
|
||||||
|
|
||||||
export type Offer = {
|
export type Offer = {
|
||||||
__typename?: 'Offer';
|
__typename?: 'Offer';
|
||||||
features?: Maybe<Array<Maybe<Feature>>>;
|
features?: Maybe<Array<Maybe<Feature>>>;
|
||||||
@@ -2831,6 +3080,8 @@ export type RootMutation = {
|
|||||||
accessToken: AccessTokenMutation;
|
accessToken: AccessTokenMutation;
|
||||||
/** Mutations that modify an Account */
|
/** Mutations that modify an Account */
|
||||||
account: AccountMutation;
|
account: AccountMutation;
|
||||||
|
/** Mutations that create, update, and delete an AccountSSOConfiguration */
|
||||||
|
accountSSOConfiguration: AccountSsoConfigurationMutation;
|
||||||
/** Mutations that modify the build credentials for an Android app */
|
/** Mutations that modify the build credentials for an Android app */
|
||||||
androidAppBuildCredentials: AndroidAppBuildCredentialsMutation;
|
androidAppBuildCredentials: AndroidAppBuildCredentialsMutation;
|
||||||
/** Mutations that modify the credentials for an Android app */
|
/** Mutations that modify the credentials for an Android app */
|
||||||
@@ -2843,6 +3094,8 @@ export type RootMutation = {
|
|||||||
app?: Maybe<AppMutation>;
|
app?: Maybe<AppMutation>;
|
||||||
/** Mutations that modify an App Store Connect Api Key */
|
/** Mutations that modify an App Store Connect Api Key */
|
||||||
appStoreConnectApiKey: AppStoreConnectApiKeyMutation;
|
appStoreConnectApiKey: AppStoreConnectApiKeyMutation;
|
||||||
|
/** Mutations that modify an AppVersion */
|
||||||
|
appVersion: AppVersionMutation;
|
||||||
/** Mutations that modify an Identifier for an iOS App */
|
/** Mutations that modify an Identifier for an iOS App */
|
||||||
appleAppIdentifier: AppleAppIdentifierMutation;
|
appleAppIdentifier: AppleAppIdentifierMutation;
|
||||||
/** Mutations that modify an Apple Device */
|
/** Mutations that modify an Apple Device */
|
||||||
@@ -2918,6 +3171,8 @@ export type RootQuery = {
|
|||||||
_doNotUse?: Maybe<Scalars['String']>;
|
_doNotUse?: Maybe<Scalars['String']>;
|
||||||
/** Top-level query object for querying Accounts. */
|
/** Top-level query object for querying Accounts. */
|
||||||
account: AccountQuery;
|
account: AccountQuery;
|
||||||
|
/** Top-level query object for querying AccountSSOConfigurationPublicData */
|
||||||
|
accountSSOConfigurationPublicData: AccountSsoConfigurationPublicDataQuery;
|
||||||
/** Top-level query object for querying Actors. */
|
/** Top-level query object for querying Actors. */
|
||||||
actor: ActorQuery;
|
actor: ActorQuery;
|
||||||
/**
|
/**
|
||||||
@@ -3108,13 +3363,20 @@ export type Submission = ActivityTimelineProjectActivity & {
|
|||||||
actor?: Maybe<Actor>;
|
actor?: Maybe<Actor>;
|
||||||
androidConfig?: Maybe<AndroidSubmissionConfig>;
|
androidConfig?: Maybe<AndroidSubmissionConfig>;
|
||||||
app: App;
|
app: App;
|
||||||
|
archiveUrl?: Maybe<Scalars['String']>;
|
||||||
|
canRetry: Scalars['Boolean'];
|
||||||
cancelingActor?: Maybe<Actor>;
|
cancelingActor?: Maybe<Actor>;
|
||||||
|
childSubmission?: Maybe<Submission>;
|
||||||
|
completedAt?: Maybe<Scalars['DateTime']>;
|
||||||
createdAt: Scalars['DateTime'];
|
createdAt: Scalars['DateTime'];
|
||||||
error?: Maybe<SubmissionError>;
|
error?: Maybe<SubmissionError>;
|
||||||
id: Scalars['ID'];
|
id: Scalars['ID'];
|
||||||
initiatingActor?: Maybe<Actor>;
|
initiatingActor?: Maybe<Actor>;
|
||||||
iosConfig?: Maybe<IosSubmissionConfig>;
|
iosConfig?: Maybe<IosSubmissionConfig>;
|
||||||
logsUrl?: Maybe<Scalars['String']>;
|
logsUrl?: Maybe<Scalars['String']>;
|
||||||
|
/** Retry time starts after completedAt */
|
||||||
|
maxRetryTimeMinutes: Scalars['Int'];
|
||||||
|
parentSubmission?: Maybe<Submission>;
|
||||||
platform: AppPlatform;
|
platform: AppPlatform;
|
||||||
status: SubmissionStatus;
|
status: SubmissionStatus;
|
||||||
submittedBuild?: Maybe<Build>;
|
submittedBuild?: Maybe<Build>;
|
||||||
@@ -3159,16 +3421,13 @@ export type SubmissionMutation = {
|
|||||||
createAndroidSubmission: CreateSubmissionResult;
|
createAndroidSubmission: CreateSubmissionResult;
|
||||||
/** Create an iOS EAS Submit submission */
|
/** Create an iOS EAS Submit submission */
|
||||||
createIosSubmission: CreateSubmissionResult;
|
createIosSubmission: CreateSubmissionResult;
|
||||||
/**
|
/** Retry an EAS Submit submission */
|
||||||
* Create an EAS Submit submission
|
retrySubmission: CreateSubmissionResult;
|
||||||
* @deprecated Use createIosSubmission / createAndroidSubmission instead
|
|
||||||
*/
|
|
||||||
createSubmission: CreateSubmissionResult;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type SubmissionMutationCancelSubmissionArgs = {
|
export type SubmissionMutationCancelSubmissionArgs = {
|
||||||
submissionId?: InputMaybe<Scalars['ID']>;
|
submissionId: Scalars['ID'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -3182,8 +3441,8 @@ export type SubmissionMutationCreateIosSubmissionArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type SubmissionMutationCreateSubmissionArgs = {
|
export type SubmissionMutationRetrySubmissionArgs = {
|
||||||
input: CreateSubmissionInput;
|
parentSubmissionId: Scalars['ID'];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SubmissionQuery = {
|
export type SubmissionQuery = {
|
||||||
@@ -3210,9 +3469,12 @@ export type SubscriptionDetails = {
|
|||||||
__typename?: 'SubscriptionDetails';
|
__typename?: 'SubscriptionDetails';
|
||||||
addons: Array<AddonDetails>;
|
addons: Array<AddonDetails>;
|
||||||
cancelledAt?: Maybe<Scalars['DateTime']>;
|
cancelledAt?: Maybe<Scalars['DateTime']>;
|
||||||
|
concurrencies?: Maybe<Concurrencies>;
|
||||||
endedAt?: Maybe<Scalars['DateTime']>;
|
endedAt?: Maybe<Scalars['DateTime']>;
|
||||||
|
futureSubscription?: Maybe<FutureSubscription>;
|
||||||
id: Scalars['ID'];
|
id: Scalars['ID'];
|
||||||
isDowngrading?: Maybe<Scalars['Boolean']>;
|
isDowngrading?: Maybe<Scalars['Boolean']>;
|
||||||
|
meteredBillingStatus: MeteredBillingStatus;
|
||||||
name?: Maybe<Scalars['String']>;
|
name?: Maybe<Scalars['String']>;
|
||||||
nextInvoice?: Maybe<Scalars['DateTime']>;
|
nextInvoice?: Maybe<Scalars['DateTime']>;
|
||||||
planId?: Maybe<Scalars['String']>;
|
planId?: Maybe<Scalars['String']>;
|
||||||
@@ -3395,8 +3657,21 @@ export enum UploadSessionType {
|
|||||||
EasSubmitAppArchive = 'EAS_SUBMIT_APP_ARCHIVE'
|
EasSubmitAppArchive = 'EAS_SUBMIT_APP_ARCHIVE'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type UsageMetricTotal = {
|
||||||
|
__typename?: 'UsageMetricTotal';
|
||||||
|
billingPeriod: BillingPeriod;
|
||||||
|
id: Scalars['ID'];
|
||||||
|
overageMetrics: Array<AccountUsageMetricAndCost>;
|
||||||
|
planMetrics: Array<AccountUsageMetricAndCost>;
|
||||||
|
/** Total cost of overages, in cents */
|
||||||
|
totalCost: Scalars['Float'];
|
||||||
|
};
|
||||||
|
|
||||||
export enum UsageMetricType {
|
export enum UsageMetricType {
|
||||||
Request = 'REQUEST'
|
Bandwidth = 'BANDWIDTH',
|
||||||
|
Build = 'BUILD',
|
||||||
|
Request = 'REQUEST',
|
||||||
|
User = 'USER'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum UsageMetricsGranularity {
|
export enum UsageMetricsGranularity {
|
||||||
@@ -4250,23 +4525,32 @@ export type CreateAppMutationVariables = Exact<{
|
|||||||
|
|
||||||
export type CreateAppMutation = { __typename?: 'RootMutation', app?: { __typename?: 'AppMutation', createApp: { __typename?: 'App', id: string } } | null };
|
export type CreateAppMutation = { __typename?: 'RootMutation', app?: { __typename?: 'AppMutation', createApp: { __typename?: 'App', id: string } } | null };
|
||||||
|
|
||||||
|
export type CreateAppVersionMutationVariables = Exact<{
|
||||||
|
appVersionInput: AppVersionInput;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type CreateAppVersionMutation = { __typename?: 'RootMutation', appVersion: { __typename?: 'AppVersionMutation', createAppVersion: { __typename?: 'AppVersion', id: string } } };
|
||||||
|
|
||||||
export type CreateAndroidBuildMutationVariables = Exact<{
|
export type CreateAndroidBuildMutationVariables = Exact<{
|
||||||
appId: Scalars['ID'];
|
appId: Scalars['ID'];
|
||||||
job: AndroidJobInput;
|
job: AndroidJobInput;
|
||||||
metadata?: InputMaybe<BuildMetadataInput>;
|
metadata?: InputMaybe<BuildMetadataInput>;
|
||||||
|
buildParams?: InputMaybe<BuildParamsInput>;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type CreateAndroidBuildMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', createAndroidBuild: { __typename?: 'CreateBuildResult', build: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt?: any | null, updatedAt?: any | null, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } }, deprecationInfo?: { __typename?: 'EASBuildDeprecationInfo', type: EasBuildDeprecationInfoType, message: string } | null } } };
|
export type CreateAndroidBuildMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', createAndroidBuild: { __typename?: 'CreateBuildResult', build: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } }, deprecationInfo?: { __typename?: 'EASBuildDeprecationInfo', type: EasBuildDeprecationInfoType, message: string } | null } } };
|
||||||
|
|
||||||
export type CreateIosBuildMutationVariables = Exact<{
|
export type CreateIosBuildMutationVariables = Exact<{
|
||||||
appId: Scalars['ID'];
|
appId: Scalars['ID'];
|
||||||
job: IosJobInput;
|
job: IosJobInput;
|
||||||
metadata?: InputMaybe<BuildMetadataInput>;
|
metadata?: InputMaybe<BuildMetadataInput>;
|
||||||
|
buildParams?: InputMaybe<BuildParamsInput>;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type CreateIosBuildMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', createIosBuild: { __typename?: 'CreateBuildResult', build: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt?: any | null, updatedAt?: any | null, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } }, deprecationInfo?: { __typename?: 'EASBuildDeprecationInfo', type: EasBuildDeprecationInfoType, message: string } | null } } };
|
export type CreateIosBuildMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', createIosBuild: { __typename?: 'CreateBuildResult', build: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } }, deprecationInfo?: { __typename?: 'EASBuildDeprecationInfo', type: EasBuildDeprecationInfoType, message: string } | null } } };
|
||||||
|
|
||||||
export type CreateEnvironmentSecretForAccountMutationVariables = Exact<{
|
export type CreateEnvironmentSecretForAccountMutationVariables = Exact<{
|
||||||
input: CreateEnvironmentSecretInput;
|
input: CreateEnvironmentSecretInput;
|
||||||
@@ -4366,6 +4650,15 @@ export type DeleteWebhookMutationVariables = Exact<{
|
|||||||
|
|
||||||
export type DeleteWebhookMutation = { __typename?: 'RootMutation', webhook: { __typename?: 'WebhookMutation', deleteWebhook: { __typename?: 'DeleteWebhookResult', id: string } } };
|
export type DeleteWebhookMutation = { __typename?: 'RootMutation', webhook: { __typename?: 'WebhookMutation', deleteWebhook: { __typename?: 'DeleteWebhookResult', id: string } } };
|
||||||
|
|
||||||
|
export type LatestAppVersionQueryVariables = Exact<{
|
||||||
|
appId: Scalars['String'];
|
||||||
|
platform: AppPlatform;
|
||||||
|
applicationIdentifier: Scalars['String'];
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type LatestAppVersionQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, latestAppVersionByPlatformAndApplicationIdentifier?: { __typename?: 'AppVersion', id: string, storeVersion: string, buildVersion: string } | null } } };
|
||||||
|
|
||||||
export type ViewBranchQueryVariables = Exact<{
|
export type ViewBranchQueryVariables = Exact<{
|
||||||
appId: Scalars['String'];
|
appId: Scalars['String'];
|
||||||
name: Scalars['String'];
|
name: Scalars['String'];
|
||||||
@@ -4379,7 +4672,7 @@ export type BuildsByIdQueryVariables = Exact<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type BuildsByIdQuery = { __typename?: 'RootQuery', builds: { __typename?: 'BuildQuery', byId: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt?: any | null, updatedAt?: any | null, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } } } };
|
export type BuildsByIdQuery = { __typename?: 'RootQuery', builds: { __typename?: 'BuildQuery', byId: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } } } };
|
||||||
|
|
||||||
export type GetAllBuildsForAppQueryVariables = Exact<{
|
export type GetAllBuildsForAppQueryVariables = Exact<{
|
||||||
appId: Scalars['String'];
|
appId: Scalars['String'];
|
||||||
@@ -4389,7 +4682,7 @@ export type GetAllBuildsForAppQueryVariables = Exact<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type GetAllBuildsForAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, builds: Array<{ __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt?: any | null, updatedAt?: any | null, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } }> } } };
|
export type GetAllBuildsForAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, builds: Array<{ __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } }> } } };
|
||||||
|
|
||||||
export type GetChannelByNameForAppQueryVariables = Exact<{
|
export type GetChannelByNameForAppQueryVariables = Exact<{
|
||||||
appId: Scalars['String'];
|
appId: Scalars['String'];
|
||||||
@@ -4458,6 +4751,7 @@ export type ViewBranchUpdatesQueryVariables = Exact<{
|
|||||||
appId: Scalars['String'];
|
appId: Scalars['String'];
|
||||||
name: Scalars['String'];
|
name: Scalars['String'];
|
||||||
limit: Scalars['Int'];
|
limit: Scalars['Int'];
|
||||||
|
offset: Scalars['Int'];
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
@@ -4485,7 +4779,7 @@ export type WebhookByIdQuery = { __typename?: 'RootQuery', webhook: { __typename
|
|||||||
|
|
||||||
export type AppFragment = { __typename?: 'App', id: string, fullName: string, slug: string };
|
export type AppFragment = { __typename?: 'App', id: string, fullName: string, slug: string };
|
||||||
|
|
||||||
export type BuildFragment = { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt?: any | null, updatedAt?: any | null, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } };
|
export type BuildFragment = { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, releaseChannel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string } };
|
||||||
|
|
||||||
export type EnvironmentSecretFragment = { __typename?: 'EnvironmentSecret', id: string, name: string, createdAt: any };
|
export type EnvironmentSecretFragment = { __typename?: 'EnvironmentSecret', id: string, name: string, createdAt: any };
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import assert from 'assert';
|
||||||
|
import gql from 'graphql-tag';
|
||||||
|
|
||||||
|
import { graphqlClient, withErrorHandlingAsync } from '../client';
|
||||||
|
import {
|
||||||
|
AppPlatform,
|
||||||
|
CreateAppVersionMutation,
|
||||||
|
CreateAppVersionMutationVariables,
|
||||||
|
} from '../generated';
|
||||||
|
|
||||||
|
export const AppVersionMutation = {
|
||||||
|
async createAppVersionAsync(appVersionInput: {
|
||||||
|
appId: string;
|
||||||
|
platform: AppPlatform;
|
||||||
|
applicationIdentifier: string;
|
||||||
|
storeVersion: string;
|
||||||
|
buildVersion: string;
|
||||||
|
runtimeVersion?: string;
|
||||||
|
}): Promise<string> {
|
||||||
|
const data = await withErrorHandlingAsync(
|
||||||
|
graphqlClient
|
||||||
|
.mutation<CreateAppVersionMutation, CreateAppVersionMutationVariables>(
|
||||||
|
gql`
|
||||||
|
mutation CreateAppVersionMutation($appVersionInput: AppVersionInput!) {
|
||||||
|
appVersion {
|
||||||
|
createAppVersion(appVersionInput: $appVersionInput) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
appVersionInput,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.toPromise()
|
||||||
|
);
|
||||||
|
const appVersionId = data.appVersion?.createAppVersion.id;
|
||||||
|
assert(appVersionId, 'AppVersion ID must be defined');
|
||||||
|
return appVersionId;
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
AndroidJobInput,
|
AndroidJobInput,
|
||||||
BuildFragment,
|
BuildFragment,
|
||||||
BuildMetadataInput,
|
BuildMetadataInput,
|
||||||
|
BuildParamsInput,
|
||||||
CreateAndroidBuildMutation,
|
CreateAndroidBuildMutation,
|
||||||
CreateAndroidBuildMutationVariables,
|
CreateAndroidBuildMutationVariables,
|
||||||
CreateIosBuildMutation,
|
CreateIosBuildMutation,
|
||||||
@@ -26,6 +27,7 @@ export const BuildMutation = {
|
|||||||
appId: string;
|
appId: string;
|
||||||
job: AndroidJobInput;
|
job: AndroidJobInput;
|
||||||
metadata: BuildMetadataInput;
|
metadata: BuildMetadataInput;
|
||||||
|
buildParams: BuildParamsInput;
|
||||||
}): Promise<BuildResult> {
|
}): Promise<BuildResult> {
|
||||||
const data = await withErrorHandlingAsync(
|
const data = await withErrorHandlingAsync(
|
||||||
graphqlClient
|
graphqlClient
|
||||||
@@ -35,9 +37,15 @@ export const BuildMutation = {
|
|||||||
$appId: ID!
|
$appId: ID!
|
||||||
$job: AndroidJobInput!
|
$job: AndroidJobInput!
|
||||||
$metadata: BuildMetadataInput
|
$metadata: BuildMetadataInput
|
||||||
|
$buildParams: BuildParamsInput
|
||||||
) {
|
) {
|
||||||
build {
|
build {
|
||||||
createAndroidBuild(appId: $appId, job: $job, metadata: $metadata) {
|
createAndroidBuild(
|
||||||
|
appId: $appId
|
||||||
|
job: $job
|
||||||
|
metadata: $metadata
|
||||||
|
buildParams: $buildParams
|
||||||
|
) {
|
||||||
build {
|
build {
|
||||||
id
|
id
|
||||||
...BuildFragment
|
...BuildFragment
|
||||||
@@ -62,6 +70,7 @@ export const BuildMutation = {
|
|||||||
appId: string;
|
appId: string;
|
||||||
job: IosJobInput;
|
job: IosJobInput;
|
||||||
metadata: BuildMetadataInput;
|
metadata: BuildMetadataInput;
|
||||||
|
buildParams: BuildParamsInput;
|
||||||
}): Promise<BuildResult> {
|
}): Promise<BuildResult> {
|
||||||
const data = await withErrorHandlingAsync(
|
const data = await withErrorHandlingAsync(
|
||||||
graphqlClient
|
graphqlClient
|
||||||
@@ -71,9 +80,15 @@ export const BuildMutation = {
|
|||||||
$appId: ID!
|
$appId: ID!
|
||||||
$job: IosJobInput!
|
$job: IosJobInput!
|
||||||
$metadata: BuildMetadataInput
|
$metadata: BuildMetadataInput
|
||||||
|
$buildParams: BuildParamsInput
|
||||||
) {
|
) {
|
||||||
build {
|
build {
|
||||||
createIosBuild(appId: $appId, job: $job, metadata: $metadata) {
|
createIosBuild(
|
||||||
|
appId: $appId
|
||||||
|
job: $job
|
||||||
|
metadata: $metadata
|
||||||
|
buildParams: $buildParams
|
||||||
|
) {
|
||||||
build {
|
build {
|
||||||
id
|
id
|
||||||
...BuildFragment
|
...BuildFragment
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import gql from 'graphql-tag';
|
||||||
|
|
||||||
|
import { graphqlClient, withErrorHandlingAsync } from '../client';
|
||||||
|
import {
|
||||||
|
AppPlatform,
|
||||||
|
AppVersion,
|
||||||
|
LatestAppVersionQuery,
|
||||||
|
LatestAppVersionQueryVariables,
|
||||||
|
} from '../generated';
|
||||||
|
|
||||||
|
export const AppVersionQuery = {
|
||||||
|
async latestVersionAsync(
|
||||||
|
appId: string,
|
||||||
|
platform: AppPlatform,
|
||||||
|
applicationIdentifier: string
|
||||||
|
): Promise<Pick<AppVersion, 'storeVersion' | 'buildVersion'> | null> {
|
||||||
|
const data = await withErrorHandlingAsync(
|
||||||
|
graphqlClient
|
||||||
|
.query<LatestAppVersionQuery, LatestAppVersionQueryVariables>(
|
||||||
|
gql`
|
||||||
|
query LatestAppVersion(
|
||||||
|
$appId: String!
|
||||||
|
$platform: AppPlatform!
|
||||||
|
$applicationIdentifier: String!
|
||||||
|
) {
|
||||||
|
app {
|
||||||
|
byId(appId: $appId) {
|
||||||
|
id
|
||||||
|
latestAppVersionByPlatformAndApplicationIdentifier(
|
||||||
|
platform: $platform
|
||||||
|
applicationIdentifier: $applicationIdentifier
|
||||||
|
) {
|
||||||
|
id
|
||||||
|
storeVersion
|
||||||
|
buildVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
{ appId, applicationIdentifier, platform },
|
||||||
|
{
|
||||||
|
additionalTypenames: ['App', 'AppVersion'],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.toPromise()
|
||||||
|
);
|
||||||
|
|
||||||
|
return data.app.byId.latestAppVersionByPlatformAndApplicationIdentifier ?? null;
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -8,7 +8,11 @@ import {
|
|||||||
ViewBranchUpdatesQueryVariables,
|
ViewBranchUpdatesQueryVariables,
|
||||||
} from '../generated';
|
} from '../generated';
|
||||||
|
|
||||||
const PAGE_LIMIT = 10_000;
|
export const viewBranchUpdatesQueryUpdateLimit = 300;
|
||||||
|
|
||||||
|
type ViewBranchUpdatesQueryVariablesWithOptionalLimitAndOffset =
|
||||||
|
Partial<ViewBranchUpdatesQueryVariables> &
|
||||||
|
Pick<ViewBranchUpdatesQueryVariables, 'appId' | 'name'>;
|
||||||
|
|
||||||
export const UpdateQuery = {
|
export const UpdateQuery = {
|
||||||
async viewAllAsync({ appId }: { appId: string }): Promise<ViewAllUpdatesQuery> {
|
async viewAllAsync({ appId }: { appId: string }): Promise<ViewAllUpdatesQuery> {
|
||||||
@@ -47,26 +51,31 @@ export const UpdateQuery = {
|
|||||||
`,
|
`,
|
||||||
{
|
{
|
||||||
appId,
|
appId,
|
||||||
limit: PAGE_LIMIT,
|
limit: viewBranchUpdatesQueryUpdateLimit,
|
||||||
},
|
},
|
||||||
{ additionalTypenames: ['UpdateBranch', 'Update'] }
|
{ additionalTypenames: ['UpdateBranch', 'Update'] }
|
||||||
)
|
)
|
||||||
.toPromise()
|
.toPromise()
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
async viewBranchAsync({ appId, name }: Pick<ViewBranchUpdatesQueryVariables, 'appId' | 'name'>) {
|
async viewBranchAsync({
|
||||||
|
appId,
|
||||||
|
name,
|
||||||
|
limit = viewBranchUpdatesQueryUpdateLimit,
|
||||||
|
offset = 0,
|
||||||
|
}: ViewBranchUpdatesQueryVariablesWithOptionalLimitAndOffset) {
|
||||||
return withErrorHandlingAsync<ViewBranchUpdatesQuery>(
|
return withErrorHandlingAsync<ViewBranchUpdatesQuery>(
|
||||||
graphqlClient
|
graphqlClient
|
||||||
.query<ViewBranchUpdatesQuery, ViewBranchUpdatesQueryVariables>(
|
.query<ViewBranchUpdatesQuery, ViewBranchUpdatesQueryVariables>(
|
||||||
gql`
|
gql`
|
||||||
query ViewBranchUpdates($appId: String!, $name: String!, $limit: Int!) {
|
query ViewBranchUpdates($appId: String!, $name: String!, $limit: Int!, $offset: Int!) {
|
||||||
app {
|
app {
|
||||||
byId(appId: $appId) {
|
byId(appId: $appId) {
|
||||||
id
|
id
|
||||||
updateBranchByName(name: $name) {
|
updateBranchByName(name: $name) {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
updates(offset: 0, limit: $limit) {
|
updates(offset: $offset, limit: $limit) {
|
||||||
id
|
id
|
||||||
group
|
group
|
||||||
message
|
message
|
||||||
@@ -92,7 +101,8 @@ export const UpdateQuery = {
|
|||||||
{
|
{
|
||||||
appId,
|
appId,
|
||||||
name,
|
name,
|
||||||
limit: PAGE_LIMIT,
|
limit,
|
||||||
|
offset,
|
||||||
},
|
},
|
||||||
{ additionalTypenames: ['UpdateBranch', 'Update'] }
|
{ additionalTypenames: ['UpdateBranch', 'Update'] }
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import { AgeRatingDeclaration, KidsAge, Rating } from '@expo/apple-utils';
|
||||||
|
|
||||||
|
import { AttributesOf } from '../../../../utils/asc';
|
||||||
|
|
||||||
|
// @ts-expect-error: Deprecated property `gamblingAndContests` needs to be deleted from the types
|
||||||
|
// These attributes is what we get from the API when no questions are answered
|
||||||
|
export const emptyAdvisory: AttributesOf<AgeRatingDeclaration> = {
|
||||||
|
alcoholTobaccoOrDrugUseOrReferences: null,
|
||||||
|
contests: null,
|
||||||
|
gamblingSimulated: null,
|
||||||
|
horrorOrFearThemes: null,
|
||||||
|
matureOrSuggestiveThemes: null,
|
||||||
|
medicalOrTreatmentInformation: null,
|
||||||
|
profanityOrCrudeHumor: null,
|
||||||
|
sexualContentGraphicAndNudity: null,
|
||||||
|
sexualContentOrNudity: null,
|
||||||
|
violenceCartoonOrFantasy: null,
|
||||||
|
violenceRealistic: null,
|
||||||
|
violenceRealisticProlongedGraphicOrSadistic: null,
|
||||||
|
gambling: false,
|
||||||
|
unrestrictedWebAccess: false,
|
||||||
|
kidsAgeBand: null,
|
||||||
|
seventeenPlus: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
// @ts-expect-error: Deprecated property `gamblingAndContests` needs to be deleted from the types
|
||||||
|
export const leastRestrictiveAdvisory: AttributesOf<AgeRatingDeclaration> = {
|
||||||
|
alcoholTobaccoOrDrugUseOrReferences: Rating.NONE,
|
||||||
|
contests: Rating.NONE,
|
||||||
|
gamblingSimulated: Rating.NONE,
|
||||||
|
horrorOrFearThemes: Rating.NONE,
|
||||||
|
matureOrSuggestiveThemes: Rating.NONE,
|
||||||
|
medicalOrTreatmentInformation: Rating.NONE,
|
||||||
|
profanityOrCrudeHumor: Rating.NONE,
|
||||||
|
sexualContentGraphicAndNudity: Rating.NONE,
|
||||||
|
sexualContentOrNudity: Rating.NONE,
|
||||||
|
violenceCartoonOrFantasy: Rating.NONE,
|
||||||
|
violenceRealistic: Rating.NONE,
|
||||||
|
violenceRealisticProlongedGraphicOrSadistic: Rating.NONE,
|
||||||
|
gambling: false,
|
||||||
|
unrestrictedWebAccess: false,
|
||||||
|
kidsAgeBand: null,
|
||||||
|
seventeenPlus: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
// @ts-expect-error: Deprecated property `gamblingAndContests` needs to be deleted from the types
|
||||||
|
export const mostRestrictiveAdvisory: AttributesOf<AgeRatingDeclaration> = {
|
||||||
|
alcoholTobaccoOrDrugUseOrReferences: Rating.FREQUENT_OR_INTENSE,
|
||||||
|
contests: Rating.FREQUENT_OR_INTENSE,
|
||||||
|
gamblingSimulated: Rating.FREQUENT_OR_INTENSE,
|
||||||
|
horrorOrFearThemes: Rating.FREQUENT_OR_INTENSE,
|
||||||
|
matureOrSuggestiveThemes: Rating.FREQUENT_OR_INTENSE,
|
||||||
|
medicalOrTreatmentInformation: Rating.FREQUENT_OR_INTENSE,
|
||||||
|
profanityOrCrudeHumor: Rating.FREQUENT_OR_INTENSE,
|
||||||
|
sexualContentGraphicAndNudity: Rating.FREQUENT_OR_INTENSE,
|
||||||
|
sexualContentOrNudity: Rating.FREQUENT_OR_INTENSE,
|
||||||
|
violenceCartoonOrFantasy: Rating.FREQUENT_OR_INTENSE,
|
||||||
|
violenceRealistic: Rating.FREQUENT_OR_INTENSE,
|
||||||
|
violenceRealisticProlongedGraphicOrSadistic: Rating.FREQUENT_OR_INTENSE,
|
||||||
|
gambling: true,
|
||||||
|
unrestrictedWebAccess: true,
|
||||||
|
kidsAgeBand: null,
|
||||||
|
seventeenPlus: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
// @ts-expect-error: Deprecated property `gamblingAndContests` needs to be deleted from the types
|
||||||
|
export const kidsSixToEightAdvisory: AttributesOf<AgeRatingDeclaration> = {
|
||||||
|
alcoholTobaccoOrDrugUseOrReferences: Rating.NONE,
|
||||||
|
contests: Rating.NONE,
|
||||||
|
gamblingSimulated: Rating.NONE,
|
||||||
|
horrorOrFearThemes: Rating.NONE,
|
||||||
|
matureOrSuggestiveThemes: Rating.NONE,
|
||||||
|
medicalOrTreatmentInformation: Rating.NONE,
|
||||||
|
profanityOrCrudeHumor: Rating.NONE,
|
||||||
|
sexualContentGraphicAndNudity: Rating.NONE,
|
||||||
|
sexualContentOrNudity: Rating.NONE,
|
||||||
|
violenceCartoonOrFantasy: Rating.NONE,
|
||||||
|
violenceRealistic: Rating.NONE,
|
||||||
|
violenceRealisticProlongedGraphicOrSadistic: Rating.NONE,
|
||||||
|
gambling: false,
|
||||||
|
unrestrictedWebAccess: false,
|
||||||
|
kidsAgeBand: KidsAge.SIX_TO_EIGHT,
|
||||||
|
seventeenPlus: false,
|
||||||
|
};
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { AppCategory, AppCategoryId, AppSubcategoryId, BundleIdPlatform } from '@expo/apple-utils';
|
||||||
|
|
||||||
|
import { AppleConfigWriter } from '../../writer';
|
||||||
|
|
||||||
|
/** Infered type of the AppleConfigWriter.setCategories attributes */
|
||||||
|
type CategoryInfoProps = Parameters<typeof AppleConfigWriter.prototype.setCategories>[0];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export a factory method instead of fixed categories.
|
||||||
|
* In the tests, we need to create a couple of different categories,
|
||||||
|
* adding them here as fixed objects won't be readable.
|
||||||
|
*/
|
||||||
|
export function makeCategory(id?: AppCategoryId | AppSubcategoryId): AppCategory | undefined {
|
||||||
|
if (!id) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AppCategory({} as any, id, {
|
||||||
|
platforms: [BundleIdPlatform.IOS, BundleIdPlatform.MAC_OS],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export a helper method to create the AppInfo object, using only AppCategoryIds or AppSubcategoryId.
|
||||||
|
*/
|
||||||
|
export function makeCategoryInfo(
|
||||||
|
attributes: Partial<Record<keyof CategoryInfoProps, AppCategoryId | AppSubcategoryId>>
|
||||||
|
): CategoryInfoProps {
|
||||||
|
return {
|
||||||
|
primaryCategory: makeCategory(attributes.primaryCategory),
|
||||||
|
primarySubcategoryOne: makeCategory(attributes.primarySubcategoryOne),
|
||||||
|
primarySubcategoryTwo: makeCategory(attributes.primarySubcategoryTwo),
|
||||||
|
secondaryCategory: makeCategory(attributes.secondaryCategory),
|
||||||
|
secondarySubcategoryOne: makeCategory(attributes.secondarySubcategoryOne),
|
||||||
|
secondarySubcategoryTwo: makeCategory(attributes.secondarySubcategoryTwo),
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { AppInfoLocalization } from '@expo/apple-utils';
|
||||||
|
|
||||||
|
import { AttributesOf } from '../../../../utils/asc';
|
||||||
|
|
||||||
|
export const englishInfo: AttributesOf<AppInfoLocalization> = {
|
||||||
|
locale: 'en-US',
|
||||||
|
name: 'Awesome test app',
|
||||||
|
subtitle: 'This is just a test',
|
||||||
|
privacyPolicyUrl: 'https://example.com/en/privacy-policy',
|
||||||
|
privacyChoicesUrl: 'https://exmaple.com/en/privacy-choices',
|
||||||
|
privacyPolicyText: 'This is some privacy policy text',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const dutchInfo: AttributesOf<AppInfoLocalization> = {
|
||||||
|
locale: 'nl-NL',
|
||||||
|
name: 'Geweldige test app',
|
||||||
|
subtitle: 'Dit is maar een test',
|
||||||
|
privacyPolicyUrl: 'https://example.com/nl/privacy-policy',
|
||||||
|
privacyChoicesUrl: 'https://example.com/nl/privacy-choices',
|
||||||
|
privacyPolicyText: 'Dit is wat privacy policy tekst',
|
||||||
|
};
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { AppStoreReviewDetail } from '@expo/apple-utils';
|
||||||
|
|
||||||
|
import { AttributesOf } from '../../../../utils/asc';
|
||||||
|
|
||||||
|
export const nameOnlyReviewDetails: AttributesOf<AppStoreReviewDetail> = {
|
||||||
|
contactFirstName: 'Evan',
|
||||||
|
contactLastName: 'Bacon',
|
||||||
|
contactEmail: '[email protected]',
|
||||||
|
contactPhone: '+1 (555) 555-5555',
|
||||||
|
demoAccountName: null,
|
||||||
|
demoAccountPassword: null,
|
||||||
|
demoAccountRequired: null,
|
||||||
|
notes: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const nameAndDemoReviewDetails: AttributesOf<AppStoreReviewDetail> = {
|
||||||
|
contactFirstName: 'Evan',
|
||||||
|
contactLastName: 'Bacon',
|
||||||
|
contactEmail: '[email protected]',
|
||||||
|
contactPhone: '+1 (555) 555-5555',
|
||||||
|
demoAccountName: '[email protected]',
|
||||||
|
demoAccountPassword: 'secretpassword',
|
||||||
|
demoAccountRequired: true,
|
||||||
|
notes: null,
|
||||||
|
};
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { AppStoreState, AppStoreVersion, Platform, ReleaseType } from '@expo/apple-utils';
|
||||||
|
|
||||||
|
import { AttributesOf } from '../../../../utils/asc';
|
||||||
|
|
||||||
|
export const manualRelease: AttributesOf<AppStoreVersion> = {
|
||||||
|
platform: Platform.IOS,
|
||||||
|
versionString: '1.0.0',
|
||||||
|
appStoreState: AppStoreState.WAITING_FOR_REVIEW,
|
||||||
|
storeIcon: null,
|
||||||
|
watchStoreIcon: null,
|
||||||
|
copyright: '2022 - ACME',
|
||||||
|
releaseType: ReleaseType.MANUAL,
|
||||||
|
earliestReleaseDate: null,
|
||||||
|
usesIdfa: null,
|
||||||
|
isWatchOnly: false,
|
||||||
|
downloadable: false,
|
||||||
|
createdDate: '2022-05-23T00:00:00.000Z',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const automaticRelease: AttributesOf<AppStoreVersion> = {
|
||||||
|
platform: Platform.IOS,
|
||||||
|
versionString: '2.0.0',
|
||||||
|
appStoreState: AppStoreState.WAITING_FOR_REVIEW,
|
||||||
|
storeIcon: null,
|
||||||
|
watchStoreIcon: null,
|
||||||
|
copyright: '2022 - ACME',
|
||||||
|
releaseType: ReleaseType.AFTER_APPROVAL,
|
||||||
|
earliestReleaseDate: null,
|
||||||
|
usesIdfa: null,
|
||||||
|
isWatchOnly: false,
|
||||||
|
downloadable: false,
|
||||||
|
createdDate: '2022-05-23T00:00:00.000Z',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const scheduledRelease: AttributesOf<AppStoreVersion> = {
|
||||||
|
platform: Platform.IOS,
|
||||||
|
versionString: '3.0.0',
|
||||||
|
appStoreState: AppStoreState.READY_FOR_SALE,
|
||||||
|
storeIcon: null,
|
||||||
|
watchStoreIcon: null,
|
||||||
|
copyright: '2022 - ACME',
|
||||||
|
releaseType: ReleaseType.SCHEDULED,
|
||||||
|
earliestReleaseDate: '2022-05-29T00:00:00.000Z',
|
||||||
|
usesIdfa: null,
|
||||||
|
isWatchOnly: false,
|
||||||
|
downloadable: false,
|
||||||
|
createdDate: '2022-05-23T00:00:00.000Z',
|
||||||
|
};
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
import { AppStoreVersionLocalization } from '@expo/apple-utils';
|
||||||
|
|
||||||
|
import { AttributesOf } from '../../../../utils/asc';
|
||||||
|
|
||||||
|
export const englishVersion: AttributesOf<AppStoreVersionLocalization> = {
|
||||||
|
locale: 'en-US',
|
||||||
|
description: 'This is a description of this version',
|
||||||
|
keywords: 'some, description',
|
||||||
|
marketingUrl: 'https://example.com/en/marketing',
|
||||||
|
promotionalText: 'This is some promotional text',
|
||||||
|
supportUrl: 'https://example.com/en/support',
|
||||||
|
whatsNew: 'Bugfixes and improvements',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const dutchVersion: AttributesOf<AppStoreVersionLocalization> = {
|
||||||
|
locale: 'nl-NL',
|
||||||
|
description: 'Dit is een beschrijving van deze versie',
|
||||||
|
keywords: 'een, beschrijving',
|
||||||
|
marketingUrl: 'https://example.com/nl/marketing',
|
||||||
|
promotionalText: 'Dit is wat promotie tekst',
|
||||||
|
supportUrl: 'https://example.com/nl/support',
|
||||||
|
whatsNew: 'Beestreparaties en verbeteringen',
|
||||||
|
};
|
||||||
Loaded 100 of 200 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user