mirror of
https://github.com/expo/eas-cli.git
synced 2026-11-14 10:08:06 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24b725438e | ||
|
|
3d2454ebf2 | ||
|
|
5caef3bc05 | ||
|
|
cc987ab71c | ||
|
|
32d3020659 | ||
|
|
17db11fa72 | ||
|
|
b5305a38cc | ||
|
|
3ec7bb7334 | ||
|
|
ceb07d4f54 | ||
|
|
92e12a57a7 | ||
|
|
373a4d40fa | ||
|
|
568faf7697 | ||
|
|
df6ff1bb7a | ||
|
|
a4a7b1c57f | ||
|
|
a9f8bfd1ff | ||
|
|
e7f687b45d | ||
|
|
666a885ba5 | ||
|
|
25c77d05f4 | ||
|
|
4b26cea3bc | ||
|
|
4aaf486e5e | ||
|
|
9a254ccf2d | ||
|
|
c8aef9dc3a | ||
|
|
f5669de55f | ||
|
|
f08965d9d2 | ||
|
|
817ed771f5 | ||
|
|
da4c41b9b7 | ||
|
|
6f47f5f691 | ||
|
|
204cd32979 | ||
|
|
f83c7d8455 | ||
|
|
5aedf13af1 | ||
|
|
39030e9a3e | ||
|
|
3ca333747f | ||
|
|
6997df3450 | ||
|
|
f939f3ceda | ||
|
|
716728a624 | ||
|
|
f8a01bade3 | ||
|
|
2cb426522d | ||
|
|
573373066d | ||
|
|
feba42f92b | ||
|
|
f373c3fc6c | ||
|
|
e1f86d779e | ||
|
|
c42a34092f | ||
|
|
ced7f924e7 | ||
|
|
93e16284ae | ||
|
|
379036a03d | ||
|
|
6035ce06ef | ||
|
|
0333fd3519 | ||
|
|
20b48326a4 | ||
|
|
199bb78b15 | ||
|
|
7e71b8eacd | ||
|
|
14bcf917a6 | ||
|
|
6ae19df305 | ||
|
|
eedc841ea6 |
No files matched your search
@@ -3,7 +3,7 @@ commentConfiguration:
|
||||
epilogue: 'Generated by [CodeMention](https://github.com/expo/expo/actions/workflows/codemention.yaml)'
|
||||
rules:
|
||||
- patterns: ['**/*']
|
||||
mentions: ['khamilowicz', 'sjchmiela', 'radoslawkrzemien']
|
||||
mentions: ['khamilowicz', 'sjchmiela']
|
||||
- patterns: ['packages/eas-cli/src/update/**']
|
||||
mentions: ['wschurman', 'quinlanj']
|
||||
- patterns: ['packages/eas-cli/src/commands/update/**']
|
||||
@@ -18,3 +18,7 @@ rules:
|
||||
mentions: ['bycedric']
|
||||
- patterns: ['packages/eas-cli/src/commands/metadata/**']
|
||||
mentions: ['bycedric']
|
||||
- patterns: ['packages/eas-cli/src/worker/**']
|
||||
mentions: ['kitten', 'kadikraman']
|
||||
- patterns: ['packages/eas-cli/src/commands/deploy/**']
|
||||
mentions: ['kitten', 'kadikraman']
|
||||
@@ -8,10 +8,95 @@ This is the log of notable changes to EAS CLI and related packages.
|
||||
|
||||
### 🎉 New features
|
||||
|
||||
- Add support for manifest host and asset host overriding for EAS Update. ([#3021](https://github.com/expo/eas-cli/pull/3021) by [@wschurman](https://github.com/wschurman))
|
||||
- Add rollout flag to update:republish. ([#3029](https://github.com/expo/eas-cli/pull/3029) by [@quinlanj](https://github.com/quinlanj))
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
## [16.6.2](https://github.com/expo/eas-cli/releases/tag/v16.6.2) - 2025-05-23
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
- Further no longer require owner field for SDK >= 53 or canary. ([#3017](https://github.com/expo/eas-cli/pull/3017) by [@wschurman](https://github.com/wschurman))
|
||||
|
||||
## [16.6.1](https://github.com/expo/eas-cli/releases/tag/v16.6.1) - 2025-05-14
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
- Onboarding: add cwd to spawned git process. ([#3015](https://github.com/expo/eas-cli/pull/3015) by [@quinlanj](https://github.com/quinlanj))
|
||||
|
||||
## [16.6.0](https://github.com/expo/eas-cli/releases/tag/v16.6.0) - 2025-05-14
|
||||
|
||||
### 🎉 New features
|
||||
|
||||
- Add support for uploading iOS internal distribution local builds. ([#3014](https://github.com/expo/eas-cli/pull/3014) by [@gabrieldonadel](https://github.com/gabrieldonadel))
|
||||
|
||||
## [16.5.0](https://github.com/expo/eas-cli/releases/tag/v16.5.0) - 2025-05-13
|
||||
|
||||
### 🎉 New features
|
||||
|
||||
- Add `--wait`/`--no-wait` flag to `eas workflow:run`. ([#3012](https://github.com/expo/eas-cli/pull/3012) by [@sjchmiela](https://github.com/sjchmiela))
|
||||
- Add `--json` flag to `eas workflow:run`. ([#3013](https://github.com/expo/eas-cli/pull/3013) by [@sjchmiela](https://github.com/sjchmiela))
|
||||
|
||||
## [16.4.2](https://github.com/expo/eas-cli/releases/tag/v16.4.2) - 2025-05-10
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
- Update `eas-build-cache-provider` function names to use `buildCacheProvider` key. ([#3002](https://github.com/expo/eas-cli/pull/3002) by [@gabrieldonadel](https://github.com/gabrieldonadel))
|
||||
|
||||
## [16.4.1](https://github.com/expo/eas-cli/releases/tag/v16.4.1) - 2025-05-07
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
- Allow non-standard build types in custom gradle command. ([#3003](https://github.com/expo/eas-cli/pull/3003) by [@khamilowicz](https://github.com/khamilowicz))
|
||||
|
||||
## [16.4.0](https://github.com/expo/eas-cli/releases/tag/v16.4.0) - 2025-05-02
|
||||
|
||||
### 🎉 New features
|
||||
|
||||
- Add `--verbose-logs` flag for `build` command ([#3000](https://github.com/expo/eas-cli/pull/3000) by [@khamilowicz](https://github.com/khamilowicz))
|
||||
- Add `eas-build-cache-provider` package. ([#3002](https://github.com/expo/eas-cli/pull/3002) by [@gabrieldonadel](https://github.com/gabrieldonadel))
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
- Read remote build cache provider types from `@expo/config`. ([#3005](https://github.com/expo/eas-cli/pull/3005) by [@gabrieldonadel](https://github.com/gabrieldonadel))
|
||||
|
||||
## [16.3.3](https://github.com/expo/eas-cli/releases/tag/v16.3.3) - 2025-04-24
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
- Add `sdk-52` alias to the list or supported android images. ([#2989](https://github.com/expo/eas-cli/pull/2989) by [@kadikraman](https://github.com/kadikraman))
|
||||
- Detect when expo metro config is used. ([#2996](https://github.com/expo/eas-cli/pull/2996) by [@kadikraman](https://github.com/kadikraman))
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
- upload assetmap.json when publishing update. ([#2994](https://github.com/expo/eas-cli/pull/2994) by [@quinlanj](https://github.com/quinlanj))
|
||||
- Add error messages for CDN-level upload errors. ([#2998](https://github.com/expo/eas-cli/pull/2998) by [@kitten](https://github.com/kitten))
|
||||
|
||||
## [16.3.2](https://github.com/expo/eas-cli/releases/tag/v16.3.2) - 2025-04-17
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
- Update upload command to display build info. ([#2990](https://github.com/expo/eas-cli/pull/2990) by [@gabrieldonadel](https://github.com/gabrieldonadel))
|
||||
- change launch asset file extension. ([#2991](https://github.com/expo/eas-cli/pull/2991) by [@quinlanj](https://github.com/quinlanj))
|
||||
|
||||
## [16.3.1](https://github.com/expo/eas-cli/releases/tag/v16.3.1) - 2025-04-11
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
- Add `--no-dev-client` flag for `build:download` command. ([#2985](https://github.com/expo/eas-cli/pull/2985) by [@gabrieldonadel](https://github.com/gabrieldonadel))
|
||||
|
||||
## [16.3.0](https://github.com/expo/eas-cli/releases/tag/v16.3.0) - 2025-04-09
|
||||
|
||||
### 🎉 New features
|
||||
|
||||
- Add `eas upload` command. ([#2932](https://github.com/expo/eas-cli/pull/2932), [#2981](https://github.com/expo/eas-cli/pull/2981), [#2983](https://github.com/expo/eas-cli/pull/2983) by [@gabrieldonadel](https://github.com/gabrieldonadel))
|
||||
- Add `eas build:download` command. ([#2982](https://github.com/expo/eas-cli/pull/2982) by [@gabrieldonadel](https://github.com/gabrieldonadel))
|
||||
|
||||
## [16.2.2](https://github.com/expo/eas-cli/releases/tag/v16.2.2) - 2025-04-08
|
||||
|
||||
## [16.2.1](https://github.com/expo/eas-cli/releases/tag/v16.2.1) - 2025-04-04
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"npmClient": "yarn",
|
||||
"version": "16.2.2",
|
||||
"version": "16.7.0",
|
||||
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
# eas-build-cache-provider
|
||||
|
||||
A build cache provider plugin for the Expo CLI
|
||||
|
||||
To use the EAS remote build provider plugin, install the `eas-build-cache-provider` package as a developer dependency:
|
||||
|
||||
```bash
|
||||
npm install --save-dev eas-build-cache-provider
|
||||
```
|
||||
|
||||
Then, update your **app.json** to include the `buildCacheProvider` property and its provider under `experiments`:
|
||||
|
||||
```json
|
||||
{
|
||||
"expo": {
|
||||
...
|
||||
"experiments": {
|
||||
"buildCacheProvider": "eas"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"name": "eas-build-cache-provider",
|
||||
"description": "A build cache provider plugin for the Expo CLI",
|
||||
"version": "16.4.2",
|
||||
"author": "Expo <[email protected]>",
|
||||
"bugs": "https://github.com/expo/eas-cli/issues",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "7.23.5",
|
||||
"@expo/config": "11.0.10",
|
||||
"@expo/spawn-async": "^1.7.2",
|
||||
"chalk": "4.1.2",
|
||||
"figures": "3.2.0",
|
||||
"fs-extra": "11.2.0",
|
||||
"getenv": "1.0.0",
|
||||
"log-symbols": "4.1.0",
|
||||
"semver": "7.5.2",
|
||||
"terminal-link": "2.1.1",
|
||||
"tslib": "2.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tsconfig/node18": "18.2.4",
|
||||
"@types/babel__code-frame": "7.0.3",
|
||||
"@types/fs-extra": "11.0.4",
|
||||
"@types/getenv": "^1.0.0",
|
||||
"memfs": "3.4.13",
|
||||
"rimraf": "3.0.2",
|
||||
"typescript": "5.3.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"homepage": "https://github.com/expo/eas-cli",
|
||||
"license": "MIT",
|
||||
"main": "build/index.js",
|
||||
"types": "build/index.d.ts",
|
||||
"repository": "expo/eas-cli",
|
||||
"scripts": {
|
||||
"build": "tsc --project tsconfig.build.json",
|
||||
"build-allow-unused": "tsc --project tsconfig.allowUnused.json",
|
||||
"watch": "yarn build --watch --preserveWatchOutput",
|
||||
"watch-allow-unused": "yarn build-allow-unused --watch --preserveWatchOutput",
|
||||
"typecheck": "tsc",
|
||||
"prepack": "yarn rebuild",
|
||||
"rebuild": "rimraf build && yarn build",
|
||||
"test": "jest",
|
||||
"clean": "rimraf build node_modules yarn-error.log"
|
||||
},
|
||||
"files": [
|
||||
"/build"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"volta": {
|
||||
"node": "20.11.0",
|
||||
"yarn": "1.22.21"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
module.exports = {
|
||||
extends: ['universe/shared/typescript-analysis'],
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.ts', '*.d.ts'],
|
||||
parserOptions: {
|
||||
project: './packages/eas-build-cache-provider/tsconfig.json',
|
||||
},
|
||||
rules: {
|
||||
'@typescript-eslint/explicit-function-return-type': [
|
||||
'warn',
|
||||
{
|
||||
allowExpressions: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
import { RunOptions, getPackageJson } from '@expo/config';
|
||||
import { SpawnResult } from '@expo/spawn-async';
|
||||
|
||||
export function isSpawnResultError(obj: any): obj is Error & SpawnResult {
|
||||
return (
|
||||
obj &&
|
||||
'message' in obj &&
|
||||
obj.status !== undefined &&
|
||||
obj.stdout !== undefined &&
|
||||
obj.stderr !== undefined
|
||||
);
|
||||
}
|
||||
|
||||
export function isDevClientBuild({
|
||||
runOptions,
|
||||
projectRoot,
|
||||
}: {
|
||||
runOptions: RunOptions;
|
||||
projectRoot: string;
|
||||
}): boolean {
|
||||
if (!hasDirectDevClientDependency(projectRoot)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ('variant' in runOptions && runOptions.variant !== undefined) {
|
||||
return runOptions.variant === 'debug';
|
||||
}
|
||||
if ('configuration' in runOptions && runOptions.configuration !== undefined) {
|
||||
return runOptions.configuration === 'Debug';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function hasDirectDevClientDependency(projectRoot: string): boolean {
|
||||
const { dependencies = {}, devDependencies = {} } = getPackageJson(projectRoot);
|
||||
return !!dependencies['expo-dev-client'] || !!devDependencies['expo-dev-client'];
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
import {
|
||||
BuildCacheProviderPlugin,
|
||||
CalculateFingerprintHashProps,
|
||||
ResolveBuildCacheProps,
|
||||
UploadBuildCacheProps,
|
||||
} from '@expo/config';
|
||||
import spawnAsync from '@expo/spawn-async';
|
||||
import chalk from 'chalk';
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
|
||||
import { isDevClientBuild, isSpawnResultError } from './helpers';
|
||||
import Log from './log';
|
||||
|
||||
async function resolveBuildCacheAsync({
|
||||
projectRoot,
|
||||
platform,
|
||||
fingerprintHash,
|
||||
runOptions,
|
||||
}: ResolveBuildCacheProps): Promise<string | null> {
|
||||
const easJsonPath = path.join(projectRoot, 'eas.json');
|
||||
if (!(await fs.exists(easJsonPath))) {
|
||||
Log.debug('eas.json not found, skip checking for remote builds');
|
||||
return null;
|
||||
}
|
||||
|
||||
Log.log(
|
||||
chalk`{whiteBright \u203A} {bold Searching builds with matching fingerprint on EAS servers}`
|
||||
);
|
||||
try {
|
||||
const results = await spawnAsync(
|
||||
'npx',
|
||||
[
|
||||
'eas-cli',
|
||||
'build:download',
|
||||
`--platform=${platform}`,
|
||||
`--fingerprint=${fingerprintHash}`,
|
||||
'--non-interactive',
|
||||
isDevClientBuild({ runOptions, projectRoot }) ? '--dev-client' : '--no-dev-client',
|
||||
'--json',
|
||||
],
|
||||
{
|
||||
cwd: projectRoot,
|
||||
}
|
||||
);
|
||||
|
||||
Log.log(chalk`{whiteBright \u203A} {bold Successfully downloaded cached build}`);
|
||||
// {
|
||||
// "path": "/var/folders/03/lppcpcnn61q3mz5ckzmzd8w80000gn/T/eas-cli-nodejs/eas-build-run-cache/c0f9ba9c-0cf1-4c5c-8566-b28b7971050f_22f1bbfa-1c09-4b67-9e4a-721906546b58.app"
|
||||
// }
|
||||
const json = JSON.parse(results.stdout.trim());
|
||||
return json?.path;
|
||||
} catch (error) {
|
||||
Log.debug('eas-cli error:', error);
|
||||
// @TODO(2025-04-11): remove this in a future release
|
||||
if (isSpawnResultError(error) && error.stderr.includes('command build:download not found')) {
|
||||
Log.warn(
|
||||
`To take advantage of EAS build cache provider, upgrade your eas-cli installation to latest.`
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function uploadBuildCacheAsync({
|
||||
projectRoot,
|
||||
platform,
|
||||
fingerprintHash,
|
||||
buildPath,
|
||||
}: UploadBuildCacheProps): Promise<string | null> {
|
||||
const easJsonPath = path.join(projectRoot, 'eas.json');
|
||||
if (!(await fs.exists(easJsonPath))) {
|
||||
Log.debug('eas.json not found, skip uploading builds');
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
Log.log(chalk`{whiteBright \u203A} {bold Uploading build to EAS}`);
|
||||
const results = await spawnAsync(
|
||||
'npx',
|
||||
[
|
||||
'eas-cli',
|
||||
'upload',
|
||||
`--platform=${platform}`,
|
||||
`--fingerprint=${fingerprintHash}`,
|
||||
buildPath ? `--build-path=${buildPath}` : '',
|
||||
'--non-interactive',
|
||||
'--json',
|
||||
],
|
||||
{
|
||||
cwd: projectRoot,
|
||||
}
|
||||
);
|
||||
// {
|
||||
// "url": "/var/folders/03/lppcpcnn61q3mz5ckzmzd8w80000gn/T/eas-cli-nodejs/eas-build-run-cache/c0f9ba9c-0cf1-4c5c-8566-b28b7971050f_22f1bbfa-1c09-4b67-9e4a-721906546b58.app"
|
||||
// }
|
||||
const json = JSON.parse(results.stdout.trim());
|
||||
Log.log(chalk`{whiteBright \u203A} {bold Build successfully uploaded: ${json?.url}}`);
|
||||
return json?.url;
|
||||
} catch (error) {
|
||||
Log.debug('eas-cli error:', error);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async function calculateEASFingerprintHashAsync({
|
||||
projectRoot,
|
||||
platform,
|
||||
}: CalculateFingerprintHashProps): Promise<string | null> {
|
||||
// prefer using `eas fingerprint:generate` because it automatically upload sources
|
||||
try {
|
||||
const results = await spawnAsync(
|
||||
'npx',
|
||||
['eas-cli', 'fingerprint:generate', `--platform=${platform}`, '--json', '--non-interactive'],
|
||||
{
|
||||
cwd: projectRoot,
|
||||
}
|
||||
);
|
||||
// {
|
||||
// "hash": "203f960b965e154b77dc31c6c42e5582e8d77196"
|
||||
// }
|
||||
const json = JSON.parse(results.stdout.trim());
|
||||
return json?.hash;
|
||||
} catch (error) {
|
||||
Log.debug('eas-cli error:', error);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const EASBuildCacheProvider: BuildCacheProviderPlugin = {
|
||||
resolveBuildCache: resolveBuildCacheAsync,
|
||||
uploadBuildCache: uploadBuildCacheAsync,
|
||||
calculateFingerprintHash: calculateEASFingerprintHashAsync,
|
||||
};
|
||||
|
||||
export default EASBuildCacheProvider;
|
||||
@@ -0,0 +1,121 @@
|
||||
import chalk from 'chalk';
|
||||
import figures from 'figures';
|
||||
import { boolish } from 'getenv';
|
||||
import logSymbols from 'log-symbols';
|
||||
import terminalLink from 'terminal-link';
|
||||
|
||||
type Color = (...text: string[]) => string;
|
||||
|
||||
export default class Log {
|
||||
public static readonly isDebug = boolish('EXPO_DEBUG', false);
|
||||
|
||||
public static log(...args: any[]): void {
|
||||
Log.consoleLog(...args);
|
||||
}
|
||||
|
||||
public static newLine(): void {
|
||||
Log.consoleLog();
|
||||
}
|
||||
|
||||
public static addNewLineIfNone(): void {
|
||||
if (!Log.isLastLineNewLine) {
|
||||
Log.newLine();
|
||||
}
|
||||
}
|
||||
|
||||
public static error(...args: any[]): void {
|
||||
Log.consoleLog(...Log.withTextColor(args, chalk.red));
|
||||
}
|
||||
|
||||
public static warn(...args: any[]): void {
|
||||
Log.consoleLog(...Log.withTextColor(args, chalk.yellow));
|
||||
}
|
||||
|
||||
public static debug(...args: any[]): void {
|
||||
if (Log.isDebug) {
|
||||
Log.consoleLog(...args);
|
||||
}
|
||||
}
|
||||
|
||||
public static gray(...args: any[]): void {
|
||||
Log.consoleLog(...Log.withTextColor(args, chalk.gray));
|
||||
}
|
||||
|
||||
public static warnDeprecatedFlag(flag: string, message: string): void {
|
||||
Log.warn(`› ${chalk.bold('--' + flag)} flag is deprecated. ${message}`);
|
||||
}
|
||||
|
||||
public static fail(message: string): void {
|
||||
Log.log(`${chalk.red(logSymbols.error)} ${message}`);
|
||||
}
|
||||
|
||||
public static succeed(message: string): void {
|
||||
Log.log(`${chalk.green(logSymbols.success)} ${message}`);
|
||||
}
|
||||
|
||||
public static withTick(...args: any[]): void {
|
||||
Log.consoleLog(chalk.green(figures.tick), ...args);
|
||||
}
|
||||
|
||||
public static withInfo(...args: any[]): void {
|
||||
Log.consoleLog(chalk.green(figures.info), ...args);
|
||||
}
|
||||
|
||||
private static consoleLog(...args: any[]): void {
|
||||
Log.updateIsLastLineNewLine(args);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(...args);
|
||||
}
|
||||
|
||||
private static withTextColor(args: any[], chalkColor: Color): string[] {
|
||||
return args.map(arg => chalkColor(arg));
|
||||
}
|
||||
|
||||
private static isLastLineNewLine = false;
|
||||
private static updateIsLastLineNewLine(args: any[]): void {
|
||||
if (args.length === 0) {
|
||||
Log.isLastLineNewLine = true;
|
||||
} else {
|
||||
const lastArg = args[args.length - 1];
|
||||
if (typeof lastArg === 'string' && (lastArg === '' || lastArg.match(/[\r\n]$/))) {
|
||||
Log.isLastLineNewLine = true;
|
||||
} else {
|
||||
Log.isLastLineNewLine = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a link for given URL, using text if provided, otherwise text is just the URL.
|
||||
* Format links as dim (unless disabled) and with an underline.
|
||||
*
|
||||
* @example https://expo.dev
|
||||
*/
|
||||
export function link(
|
||||
url: string,
|
||||
{ text = url, fallback, dim = true }: { text?: string; dim?: boolean; fallback?: string } = {}
|
||||
): string {
|
||||
// Links can be disabled via env variables https://github.com/jamestalmage/supports-hyperlinks/blob/master/index.js
|
||||
const output = terminalLink(text, url, {
|
||||
fallback: () =>
|
||||
fallback ?? (text === url ? chalk.underline(url) : `${text}: ${chalk.underline(url)}`),
|
||||
});
|
||||
return dim ? chalk.dim(output) : output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a consistent "Learn more" link experience.
|
||||
* Format links as dim (unless disabled) with an underline.
|
||||
*
|
||||
* @example Learn more: https://expo.dev
|
||||
*/
|
||||
export function learnMore(
|
||||
url: string,
|
||||
{
|
||||
learnMoreMessage: maybeLearnMoreMessage,
|
||||
dim = true,
|
||||
}: { learnMoreMessage?: string; dim?: boolean } = {}
|
||||
): string {
|
||||
return link(url, { text: maybeLearnMoreMessage ?? 'Learn more', dim });
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "./tsconfig",
|
||||
"exclude": ["**/__mocks__/*", "**/__tests__/*"]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": "@tsconfig/node18/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"importHelpers": true,
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"outDir": "build",
|
||||
"rootDir": "src",
|
||||
"typeRoots": ["../../node_modules/@types", "../../ts-declarations", "./node_modules/@types"]
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
}
|
||||
+115
-81
@@ -70,6 +70,7 @@ eas --help COMMAND
|
||||
* [`eas build:configure`](#eas-buildconfigure)
|
||||
* [`eas build:delete [BUILD_ID]`](#eas-builddelete-build_id)
|
||||
* [`eas build:dev`](#eas-builddev)
|
||||
* [`eas build:download`](#eas-builddownload)
|
||||
* [`eas build:inspect`](#eas-buildinspect)
|
||||
* [`eas build:list`](#eas-buildlist)
|
||||
* [`eas build:resign`](#eas-buildresign)
|
||||
@@ -161,7 +162,7 @@ ALIASES
|
||||
$ eas login
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/account/login.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/account/login.ts)_
|
||||
|
||||
## `eas account:logout`
|
||||
|
||||
@@ -178,7 +179,7 @@ ALIASES
|
||||
$ eas logout
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/account/logout.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/account/logout.ts)_
|
||||
|
||||
## `eas account:view`
|
||||
|
||||
@@ -195,7 +196,7 @@ ALIASES
|
||||
$ eas whoami
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/account/view.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/account/view.ts)_
|
||||
|
||||
## `eas analytics [STATUS]`
|
||||
|
||||
@@ -209,7 +210,7 @@ DESCRIPTION
|
||||
display or change analytics settings
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/analytics.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/analytics.ts)_
|
||||
|
||||
## `eas autocomplete [SHELL]`
|
||||
|
||||
@@ -261,7 +262,7 @@ DESCRIPTION
|
||||
create a branch
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/branch/create.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/branch/create.ts)_
|
||||
|
||||
## `eas branch:delete [NAME]`
|
||||
|
||||
@@ -282,7 +283,7 @@ DESCRIPTION
|
||||
delete a branch
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/branch/delete.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/branch/delete.ts)_
|
||||
|
||||
## `eas branch:list`
|
||||
|
||||
@@ -302,7 +303,7 @@ DESCRIPTION
|
||||
list all branches
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/branch/list.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/branch/list.ts)_
|
||||
|
||||
## `eas branch:rename`
|
||||
|
||||
@@ -322,7 +323,7 @@ DESCRIPTION
|
||||
rename a branch
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/branch/rename.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/branch/rename.ts)_
|
||||
|
||||
## `eas branch:view [NAME]`
|
||||
|
||||
@@ -345,7 +346,7 @@ DESCRIPTION
|
||||
view a branch
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/branch/view.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/branch/view.ts)_
|
||||
|
||||
## `eas build`
|
||||
|
||||
@@ -355,7 +356,7 @@ start a build
|
||||
USAGE
|
||||
$ eas build [-p android|ios|all] [-e <value>] [--local] [--output <value>] [--wait] [--clear-cache] [-s |
|
||||
--auto-submit-with-profile <value>] [-m <value>] [--build-logger-level trace|debug|info|warn|error|fatal]
|
||||
[--freeze-credentials] [--json --non-interactive]
|
||||
[--freeze-credentials] [--verbose-logs] [--json --non-interactive]
|
||||
|
||||
FLAGS
|
||||
-e, --profile=PROFILE_NAME Name of the build profile from eas.json. Defaults to
|
||||
@@ -376,13 +377,14 @@ FLAGS
|
||||
--local Run build locally [experimental]
|
||||
--non-interactive Run the command in non-interactive mode.
|
||||
--output=<value> Output path for local build
|
||||
--verbose-logs Use verbose logs for the build process
|
||||
--[no-]wait Wait for build(s) to complete
|
||||
|
||||
DESCRIPTION
|
||||
start a build
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/build/index.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/build/index.ts)_
|
||||
|
||||
## `eas build:cancel [BUILD_ID]`
|
||||
|
||||
@@ -401,7 +403,7 @@ DESCRIPTION
|
||||
cancel a build
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/build/cancel.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/build/cancel.ts)_
|
||||
|
||||
## `eas build:configure`
|
||||
|
||||
@@ -418,7 +420,7 @@ DESCRIPTION
|
||||
configure the project to support EAS Build
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/build/configure.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/build/configure.ts)_
|
||||
|
||||
## `eas build:delete [BUILD_ID]`
|
||||
|
||||
@@ -437,7 +439,7 @@ DESCRIPTION
|
||||
delete a build
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/delete.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/build/delete.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/build/delete.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/build/delete.ts)_
|
||||
|
||||
## `eas build:dev`
|
||||
|
||||
@@ -457,7 +459,28 @@ DESCRIPTION
|
||||
run dev client simulator/emulator build with matching fingerprint or create a new one
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/dev.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/build/dev.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/build/dev.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/build/dev.ts)_
|
||||
|
||||
## `eas build:download`
|
||||
|
||||
download simulator/emulator builds for a given fingerprint hash
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas build:download --fingerprint <value> [-p ios|android] [--dev-client] [--json --non-interactive]
|
||||
|
||||
FLAGS
|
||||
-p, --platform=(ios|android)
|
||||
--[no-]dev-client Filter only dev-client builds.
|
||||
--fingerprint=<value> (required) Fingerprint hash of the build to download
|
||||
--json Enable JSON output, non-JSON messages will be printed to stderr.
|
||||
--non-interactive Run the command in non-interactive mode.
|
||||
|
||||
DESCRIPTION
|
||||
download simulator/emulator builds for a given fingerprint hash
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/download.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/build/download.ts)_
|
||||
|
||||
## `eas build:inspect`
|
||||
|
||||
@@ -492,7 +515,7 @@ DESCRIPTION
|
||||
inspect the state of the project at specific build stages, useful for troubleshooting
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/build/inspect.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/build/inspect.ts)_
|
||||
|
||||
## `eas build:list`
|
||||
|
||||
@@ -544,7 +567,7 @@ DESCRIPTION
|
||||
list all builds for your project
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/build/list.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/build/list.ts)_
|
||||
|
||||
## `eas build:resign`
|
||||
|
||||
@@ -573,7 +596,7 @@ DESCRIPTION
|
||||
re-sign a build archive
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/build/resign.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/build/resign.ts)_
|
||||
|
||||
## `eas build:run`
|
||||
|
||||
@@ -599,7 +622,7 @@ DESCRIPTION
|
||||
run simulator/emulator builds from eas-cli
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/build/run.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/build/run.ts)_
|
||||
|
||||
## `eas build:submit`
|
||||
|
||||
@@ -649,7 +672,7 @@ DESCRIPTION
|
||||
get the latest version from EAS servers
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/version/get.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/build/version/get.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/build/version/get.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/build/version/get.ts)_
|
||||
|
||||
## `eas build:version:set`
|
||||
|
||||
@@ -668,7 +691,7 @@ DESCRIPTION
|
||||
update version of an app
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/build/version/set.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/build/version/set.ts)_
|
||||
|
||||
## `eas build:version:sync`
|
||||
|
||||
@@ -687,7 +710,7 @@ DESCRIPTION
|
||||
update a version in native code with a value stored on EAS servers
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/version/sync.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/build/version/sync.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/build/version/sync.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/build/version/sync.ts)_
|
||||
|
||||
## `eas build:view [BUILD_ID]`
|
||||
|
||||
@@ -704,7 +727,7 @@ DESCRIPTION
|
||||
view a build for your project
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/build/view.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/build/view.ts)_
|
||||
|
||||
## `eas channel:create [NAME]`
|
||||
|
||||
@@ -725,7 +748,7 @@ DESCRIPTION
|
||||
create a channel
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/channel/create.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/channel/create.ts)_
|
||||
|
||||
## `eas channel:edit [NAME]`
|
||||
|
||||
@@ -747,7 +770,7 @@ DESCRIPTION
|
||||
point a channel at a new branch
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/channel/edit.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/channel/edit.ts)_
|
||||
|
||||
## `eas channel:list`
|
||||
|
||||
@@ -767,7 +790,7 @@ DESCRIPTION
|
||||
list all channels
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/channel/list.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/channel/list.ts)_
|
||||
|
||||
## `eas channel:pause [NAME]`
|
||||
|
||||
@@ -789,7 +812,7 @@ DESCRIPTION
|
||||
pause a channel to stop it from sending updates
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/channel/pause.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/channel/pause.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/channel/pause.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/channel/pause.ts)_
|
||||
|
||||
## `eas channel:resume [NAME]`
|
||||
|
||||
@@ -811,7 +834,7 @@ DESCRIPTION
|
||||
resume a channel to start sending updates
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/channel/resume.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/channel/resume.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/channel/resume.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/channel/resume.ts)_
|
||||
|
||||
## `eas channel:rollout [CHANNEL]`
|
||||
|
||||
@@ -844,7 +867,7 @@ DESCRIPTION
|
||||
Roll a new branch out on a channel incrementally.
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/channel/rollout.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/channel/rollout.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/channel/rollout.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/channel/rollout.ts)_
|
||||
|
||||
## `eas channel:view [NAME]`
|
||||
|
||||
@@ -867,7 +890,7 @@ DESCRIPTION
|
||||
view a channel
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/channel/view.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/channel/view.ts)_
|
||||
|
||||
## `eas config`
|
||||
|
||||
@@ -888,7 +911,7 @@ DESCRIPTION
|
||||
display project configuration (app.json + eas.json)
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/config.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/config.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/config.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/config.ts)_
|
||||
|
||||
## `eas credentials`
|
||||
|
||||
@@ -905,7 +928,7 @@ DESCRIPTION
|
||||
manage credentials
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/credentials/index.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/credentials/index.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/credentials/index.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/credentials/index.ts)_
|
||||
|
||||
## `eas credentials:configure-build`
|
||||
|
||||
@@ -923,7 +946,7 @@ DESCRIPTION
|
||||
Set up credentials for building your project.
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/credentials/configure-build.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/credentials/configure-build.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/credentials/configure-build.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/credentials/configure-build.ts)_
|
||||
|
||||
## `eas deploy [2m[options][22m`
|
||||
|
||||
@@ -951,7 +974,7 @@ ALIASES
|
||||
$ eas worker:deploy
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/deploy/index.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/deploy/index.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/deploy/index.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/deploy/index.ts)_
|
||||
|
||||
## `eas deploy:alias`
|
||||
|
||||
@@ -976,7 +999,7 @@ ALIASES
|
||||
$ eas deploy:promote
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/deploy/alias.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/deploy/alias.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/deploy/alias.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/deploy/alias.ts)_
|
||||
|
||||
## `eas deploy:promote`
|
||||
|
||||
@@ -1013,7 +1036,7 @@ DESCRIPTION
|
||||
register new Apple Devices to use for internal distribution
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/device/create.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/device/create.ts)_
|
||||
|
||||
## `eas device:delete`
|
||||
|
||||
@@ -1033,7 +1056,7 @@ DESCRIPTION
|
||||
remove a registered device from your account
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/device/delete.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/device/delete.ts)_
|
||||
|
||||
## `eas device:list`
|
||||
|
||||
@@ -1054,7 +1077,7 @@ DESCRIPTION
|
||||
list all registered devices for your account
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/device/list.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/device/list.ts)_
|
||||
|
||||
## `eas device:rename`
|
||||
|
||||
@@ -1075,7 +1098,7 @@ DESCRIPTION
|
||||
rename a registered device
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/device/rename.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/device/rename.ts)_
|
||||
|
||||
## `eas device:view [UDID]`
|
||||
|
||||
@@ -1089,7 +1112,7 @@ DESCRIPTION
|
||||
view a device for your project
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/device/view.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/device/view.ts)_
|
||||
|
||||
## `eas diagnostics`
|
||||
|
||||
@@ -1103,7 +1126,7 @@ DESCRIPTION
|
||||
display environment info
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/diagnostics.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/diagnostics.ts)_
|
||||
|
||||
## `eas env:create [ENVIRONMENT]`
|
||||
|
||||
@@ -1132,7 +1155,7 @@ DESCRIPTION
|
||||
create an environment variable for the current project or account
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/env/create.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/env/create.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/env/create.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/env/create.ts)_
|
||||
|
||||
## `eas env:delete [ENVIRONMENT]`
|
||||
|
||||
@@ -1156,7 +1179,7 @@ DESCRIPTION
|
||||
delete an environment variable for the current project or account
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/env/delete.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/env/delete.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/env/delete.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/env/delete.ts)_
|
||||
|
||||
## `eas env:exec ENVIRONMENT BASH_COMMAND`
|
||||
|
||||
@@ -1177,7 +1200,7 @@ DESCRIPTION
|
||||
execute a command with environment variables from the selected environment
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/env/exec.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/env/exec.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/env/exec.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/env/exec.ts)_
|
||||
|
||||
## `eas env:get [ENVIRONMENT]`
|
||||
|
||||
@@ -1202,7 +1225,7 @@ DESCRIPTION
|
||||
view an environment variable for the current project or account
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/env/get.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/env/get.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/env/get.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/env/get.ts)_
|
||||
|
||||
## `eas env:list [ENVIRONMENT]`
|
||||
|
||||
@@ -1227,7 +1250,7 @@ DESCRIPTION
|
||||
list environment variables for the current project or account
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/env/list.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/env/list.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/env/list.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/env/list.ts)_
|
||||
|
||||
## `eas env:pull [ENVIRONMENT]`
|
||||
|
||||
@@ -1250,7 +1273,7 @@ DESCRIPTION
|
||||
pull environment variables for the selected environment to .env file
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/env/pull.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/env/pull.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/env/pull.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/env/pull.ts)_
|
||||
|
||||
## `eas env:push [ENVIRONMENT]`
|
||||
|
||||
@@ -1271,7 +1294,7 @@ DESCRIPTION
|
||||
push environment variables from .env file to the selected environment
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/env/push.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/env/push.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/env/push.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/env/push.ts)_
|
||||
|
||||
## `eas env:update [ENVIRONMENT]`
|
||||
|
||||
@@ -1302,7 +1325,7 @@ DESCRIPTION
|
||||
update an environment variable on the current project or account
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/env/update.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/env/update.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/env/update.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/env/update.ts)_
|
||||
|
||||
## `eas fingerprint:compare [HASH1] [HASH2]`
|
||||
|
||||
@@ -1347,7 +1370,7 @@ EXAMPLES
|
||||
$ eas fingerprint:compare <FINGERPRINT-HASH> --update-id <UPDATE-ID> # Compare fingerprint from update against provided fingerprint
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/fingerprint/compare.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/fingerprint/compare.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/fingerprint/compare.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/fingerprint/compare.ts)_
|
||||
|
||||
## `eas fingerprint:generate`
|
||||
|
||||
@@ -1378,7 +1401,7 @@ EXAMPLES
|
||||
$ eas fingerprint:generate --json --non-interactive --platform android # Output fingerprint json to stdout
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/fingerprint/generate.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/fingerprint/generate.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/fingerprint/generate.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/fingerprint/generate.ts)_
|
||||
|
||||
## `eas help [COMMAND]`
|
||||
|
||||
@@ -1486,7 +1509,7 @@ DESCRIPTION
|
||||
validate the local store configuration
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/metadata/lint.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/metadata/lint.ts)_
|
||||
|
||||
## `eas metadata:pull`
|
||||
|
||||
@@ -1503,7 +1526,7 @@ DESCRIPTION
|
||||
generate the local store configuration from the app stores
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/metadata/pull.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/metadata/pull.ts)_
|
||||
|
||||
## `eas metadata:push`
|
||||
|
||||
@@ -1520,7 +1543,7 @@ DESCRIPTION
|
||||
sync the local store configuration to the app stores
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/metadata/push.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/metadata/push.ts)_
|
||||
|
||||
## `eas onboarding [TARGET_PROJECT_DIRECTORY]`
|
||||
|
||||
@@ -1550,7 +1573,7 @@ DESCRIPTION
|
||||
open the project page in a web browser
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/open.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/open.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/open.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/open.ts)_
|
||||
|
||||
## `eas project:info`
|
||||
|
||||
@@ -1564,7 +1587,7 @@ DESCRIPTION
|
||||
information about the current project
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/project/info.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/project/info.ts)_
|
||||
|
||||
## `eas project:init`
|
||||
|
||||
@@ -1587,7 +1610,7 @@ ALIASES
|
||||
$ eas init
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/project/init.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/project/init.ts)_
|
||||
|
||||
## `eas project:onboarding [TARGET_PROJECT_DIRECTORY]`
|
||||
|
||||
@@ -1605,7 +1628,7 @@ ALIASES
|
||||
$ eas onboarding
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/project/onboarding.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/project/onboarding.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/project/onboarding.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/project/onboarding.ts)_
|
||||
|
||||
## `eas submit`
|
||||
|
||||
@@ -1636,7 +1659,7 @@ ALIASES
|
||||
$ eas build:submit
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/submit.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/submit.ts)_
|
||||
|
||||
## `eas update`
|
||||
|
||||
@@ -1678,7 +1701,7 @@ DESCRIPTION
|
||||
publish an update group
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/update/index.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/update/index.ts)_
|
||||
|
||||
## `eas update:configure`
|
||||
|
||||
@@ -1698,7 +1721,7 @@ DESCRIPTION
|
||||
configure the project to support EAS Update
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/update/configure.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/update/configure.ts)_
|
||||
|
||||
## `eas update:delete GROUPID`
|
||||
|
||||
@@ -1719,7 +1742,7 @@ DESCRIPTION
|
||||
delete all the updates in an update group
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/update/delete.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/update/delete.ts)_
|
||||
|
||||
## `eas update:edit [GROUPID]`
|
||||
|
||||
@@ -1743,7 +1766,7 @@ DESCRIPTION
|
||||
edit all the updates in an update group
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/update/edit.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/update/edit.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/update/edit.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/update/edit.ts)_
|
||||
|
||||
## `eas update:list`
|
||||
|
||||
@@ -1765,7 +1788,7 @@ DESCRIPTION
|
||||
view the recent updates
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/update/list.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/update/list.ts)_
|
||||
|
||||
## `eas update:republish`
|
||||
|
||||
@@ -1774,8 +1797,8 @@ roll back to an existing update
|
||||
```
|
||||
USAGE
|
||||
$ eas update:republish [--channel <value> | --branch <value> | --group <value>] [--destination-channel <value> |
|
||||
--destination-branch <value>] [-m <value>] [-p android|ios|all] [--private-key-path <value>] [--json
|
||||
--non-interactive]
|
||||
--destination-branch <value>] [-m <value>] [-p android|ios|all] [--private-key-path <value>] [--rollout-percentage
|
||||
<value>] [--json --non-interactive]
|
||||
|
||||
FLAGS
|
||||
-m, --message=<value> Short message describing the republished update group
|
||||
@@ -1792,12 +1815,16 @@ FLAGS
|
||||
expo-updates' configuration. Defaults to a file named "private-key.pem" in the
|
||||
certificate's directory. Only relevant if you are using code signing:
|
||||
https://docs.expo.dev/eas-update/code-signing/
|
||||
--rollout-percentage=<value> Percentage of users this update should be immediately available to. Users not in the
|
||||
rollout will be served the previous latest update on the branch, even if that update
|
||||
is itself being rolled out. The specified number must be an integer between 1 and
|
||||
100. When not specified, this defaults to 100.
|
||||
|
||||
DESCRIPTION
|
||||
roll back to an existing update
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/update/republish.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/update/republish.ts)_
|
||||
|
||||
## `eas update:roll-back-to-embedded`
|
||||
|
||||
@@ -1825,7 +1852,7 @@ DESCRIPTION
|
||||
roll back to the embedded update
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/update/roll-back-to-embedded.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/update/roll-back-to-embedded.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/update/roll-back-to-embedded.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/update/roll-back-to-embedded.ts)_
|
||||
|
||||
## `eas update:rollback`
|
||||
|
||||
@@ -1845,7 +1872,7 @@ DESCRIPTION
|
||||
roll back to an embedded update or an existing update
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/update/rollback.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/update/rollback.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/update/rollback.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/update/rollback.ts)_
|
||||
|
||||
## `eas update:view GROUPID`
|
||||
|
||||
@@ -1865,7 +1892,7 @@ DESCRIPTION
|
||||
update group details
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/update/view.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/update/view.ts)_
|
||||
|
||||
## `eas webhook:create`
|
||||
|
||||
@@ -1886,7 +1913,7 @@ DESCRIPTION
|
||||
create a webhook
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/webhook/create.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/webhook/create.ts)_
|
||||
|
||||
## `eas webhook:delete [ID]`
|
||||
|
||||
@@ -1906,7 +1933,7 @@ DESCRIPTION
|
||||
delete a webhook
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/webhook/delete.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/webhook/delete.ts)_
|
||||
|
||||
## `eas webhook:list`
|
||||
|
||||
@@ -1924,7 +1951,7 @@ DESCRIPTION
|
||||
list webhooks
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/webhook/list.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/webhook/list.ts)_
|
||||
|
||||
## `eas webhook:update`
|
||||
|
||||
@@ -1946,7 +1973,7 @@ DESCRIPTION
|
||||
update a webhook
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/webhook/update.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/webhook/update.ts)_
|
||||
|
||||
## `eas webhook:view ID`
|
||||
|
||||
@@ -1963,7 +1990,7 @@ DESCRIPTION
|
||||
view a webhook
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/webhook/view.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/webhook/view.ts)_
|
||||
|
||||
## `eas whoami`
|
||||
|
||||
@@ -2047,27 +2074,34 @@ DESCRIPTION
|
||||
create a new workflow configuration YAML file
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/workflow/create.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/workflow/create.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/workflow/create.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/workflow/create.ts)_
|
||||
|
||||
## `eas workflow:run [FILE]`
|
||||
|
||||
Run an EAS workflow
|
||||
run an EAS workflow
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas workflow:run [FILE] [--non-interactive]
|
||||
$ eas workflow:run [FILE] [--non-interactive] [--wait] [--json]
|
||||
|
||||
ARGUMENTS
|
||||
FILE Path to the workflow file to run
|
||||
|
||||
FLAGS
|
||||
--json Enable JSON output, non-JSON messages will be printed to stderr.
|
||||
--non-interactive Run the command in non-interactive mode.
|
||||
--[no-]wait Wait for workflow run to complete
|
||||
|
||||
DESCRIPTION
|
||||
Run an EAS workflow
|
||||
run an EAS workflow
|
||||
|
||||
FLAG DESCRIPTIONS
|
||||
--[no-]wait Wait for workflow run to complete
|
||||
|
||||
Exit codes: 0 = success, 11 = failure, 12 = canceled, 13 = wait aborted.
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/workflow/run.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/workflow/run.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/workflow/run.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/workflow/run.ts)_
|
||||
|
||||
## `eas workflow:validate PATH`
|
||||
|
||||
@@ -2087,5 +2121,5 @@ DESCRIPTION
|
||||
validate a workflow configuration yaml file
|
||||
```
|
||||
|
||||
_See code: [packages/eas-cli/src/commands/workflow/validate.ts](https://github.com/expo/eas-cli/blob/v16.2.2/packages/eas-cli/src/commands/workflow/validate.ts)_
|
||||
_See code: [packages/eas-cli/src/commands/workflow/validate.ts](https://github.com/expo/eas-cli/blob/v16.7.0/packages/eas-cli/src/commands/workflow/validate.ts)_
|
||||
<!-- commandsstop -->
|
||||
Generated
+1056
-101
File diff suppressed because it is too large.
Load diff
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "eas-cli",
|
||||
"description": "EAS command line tool",
|
||||
"version": "16.2.2",
|
||||
"version": "16.7.0",
|
||||
"author": "Expo <[email protected]>",
|
||||
"bin": {
|
||||
"eas": "./bin/run"
|
||||
@@ -13,7 +13,7 @@
|
||||
"@expo/config": "10.0.6",
|
||||
"@expo/config-plugins": "9.0.12",
|
||||
"@expo/eas-build-job": "1.0.173",
|
||||
"@expo/eas-json": "16.1.0",
|
||||
"@expo/eas-json": "16.7.0",
|
||||
"@expo/env": "^1.0.0",
|
||||
"@expo/json-file": "8.3.3",
|
||||
"@expo/logger": "1.0.117",
|
||||
@@ -38,6 +38,7 @@
|
||||
"ajv": "8.11.0",
|
||||
"ajv-formats": "2.1.1",
|
||||
"better-opn": "3.0.2",
|
||||
"bplist-parser": "^0.3.0",
|
||||
"chalk": "4.1.2",
|
||||
"cli-progress": "3.12.0",
|
||||
"dateformat": "4.6.3",
|
||||
|
||||
@@ -95,7 +95,11 @@ export function getExpoWebsiteBaseUrl(): string {
|
||||
}
|
||||
}
|
||||
|
||||
export function getEASUpdateURL(projectId: string): string {
|
||||
export function getEASUpdateURL(projectId: string, manifestHostOverride: string | null): string {
|
||||
if (manifestHostOverride) {
|
||||
return new URL(projectId, `https://${manifestHostOverride}`).href;
|
||||
}
|
||||
|
||||
if (process.env.EXPO_STAGING) {
|
||||
return new URL(projectId, `https://staging-u.expo.dev`).href;
|
||||
} else if (process.env.EXPO_LOCAL) {
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import Log from '../../../log';
|
||||
import { maybeWarnAboutNonStandardBuildType } from '../build';
|
||||
|
||||
const warn = jest.spyOn(Log, 'warn');
|
||||
|
||||
describe('maybeWarnAboutNonStandardBuildType', () => {
|
||||
it('should not warn about non-standard build type', () => {
|
||||
const buildProfile = {
|
||||
gradleCommand: ':app:buildRelease',
|
||||
};
|
||||
|
||||
maybeWarnAboutNonStandardBuildType({ buildProfile, buildType: 'release' });
|
||||
|
||||
expect(warn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should warn about non-standard build type', () => {
|
||||
const buildProfile = {
|
||||
gradleCommand: ':app:buildStage',
|
||||
};
|
||||
|
||||
maybeWarnAboutNonStandardBuildType({ buildProfile, buildType: 'stage' });
|
||||
|
||||
expect(warn).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Android, Metadata, Platform, Workflow } from '@expo/eas-build-job';
|
||||
import { AppVersionSource } from '@expo/eas-json';
|
||||
import chalk from 'chalk';
|
||||
import getenv from 'getenv';
|
||||
import nullthrows from 'nullthrows';
|
||||
|
||||
import { transformJob } from './graphql';
|
||||
@@ -12,7 +13,7 @@ import AndroidCredentialsProvider, {
|
||||
} from '../../credentials/android/AndroidCredentialsProvider';
|
||||
import { BuildParamsInput } from '../../graphql/generated';
|
||||
import { BuildMutation, BuildResult } from '../../graphql/mutations/BuildMutation';
|
||||
import Log from '../../log';
|
||||
import Log, { learnMore } from '../../log';
|
||||
import {
|
||||
ensureApplicationIdIsDefinedForManagedProjectAsync,
|
||||
getApplicationIdAsync,
|
||||
@@ -65,6 +66,10 @@ This means that it will most likely produce an AAB and you will not be able to i
|
||||
ctx.vcsClient
|
||||
);
|
||||
|
||||
if (gradleContext?.buildType) {
|
||||
maybeWarnAboutNonStandardBuildType({ buildProfile, buildType: gradleContext.buildType });
|
||||
}
|
||||
|
||||
if (ctx.workflow === Workflow.MANAGED) {
|
||||
await ensureApplicationIdIsDefinedForManagedProjectAsync(ctx);
|
||||
}
|
||||
@@ -168,3 +173,38 @@ async function ensureAndroidCredentialsAsync(
|
||||
source: credentialsSource,
|
||||
};
|
||||
}
|
||||
|
||||
export function maybeWarnAboutNonStandardBuildType({
|
||||
buildProfile,
|
||||
buildType,
|
||||
}: {
|
||||
buildProfile: Pick<CommonContext<Platform.ANDROID>['buildProfile'], 'gradleCommand'>;
|
||||
buildType: string;
|
||||
}): void {
|
||||
const shouldSuppressWarning = getenv.boolish('EAS_BUILD_NO_GRADLE_BUILD_TYPE_WARNING', false);
|
||||
|
||||
if (shouldSuppressWarning) {
|
||||
return;
|
||||
}
|
||||
|
||||
const knownValidBuildTypes = ['debug', 'release'];
|
||||
if (!knownValidBuildTypes.includes(buildType)) {
|
||||
Log.warn(
|
||||
`Custom gradle command "${chalk.bold(
|
||||
buildProfile.gradleCommand
|
||||
)}" has non-standard build type: "${chalk.bold(
|
||||
buildType
|
||||
)}". Expected the command to end with "${chalk.bold('...Debug')}" or "${chalk.bold(
|
||||
'...Release'
|
||||
)}"`
|
||||
);
|
||||
Log.warn(
|
||||
`Ensure the command is spelled correctly and ${chalk.bold(
|
||||
'build.gradle'
|
||||
)} is configured correctly. To suppress this warning, set ${chalk.bold(
|
||||
'EAS_BUILD_NO_GRADLE_BUILD_TYPE_WARNING=true'
|
||||
)}.`
|
||||
);
|
||||
Log.warn(learnMore('https://developer.android.com/build/build-variants#build-types'));
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import slash from 'slash';
|
||||
|
||||
import { AndroidCredentials } from '../../credentials/android/AndroidCredentialsProvider';
|
||||
import { getCustomBuildConfigPathForJob } from '../../project/customBuildConfig';
|
||||
import { getUsername } from '../../project/projectUtils';
|
||||
import { getUsernameForBuildMetadataAndBuildJob } from '../../project/projectUtils';
|
||||
import { BuildContext } from '../context';
|
||||
|
||||
interface JobData {
|
||||
@@ -29,7 +29,7 @@ export async function prepareJobAsync(
|
||||
ctx: BuildContext<Platform.ANDROID>,
|
||||
jobData: JobData
|
||||
): Promise<Android.Job> {
|
||||
const username = getUsername(ctx.exp, ctx.user);
|
||||
const username = getUsernameForBuildMetadataAndBuildJob(ctx.user);
|
||||
const buildProfile: BuildProfile<Platform.ANDROID> = ctx.buildProfile;
|
||||
const projectRootDirectory =
|
||||
slash(path.relative(await ctx.vcsClient.getRootPathAsync(), ctx.projectDir)) || '.';
|
||||
@@ -78,7 +78,10 @@ export async function prepareJobAsync(
|
||||
bun: buildProfile.bun,
|
||||
yarn: buildProfile.yarn,
|
||||
ndk: buildProfile.ndk,
|
||||
env: buildProfile.env,
|
||||
env: {
|
||||
...buildProfile.env,
|
||||
...(ctx.isVerboseLoggingEnabled ? { EAS_VERBOSE: '1' } : {}),
|
||||
},
|
||||
},
|
||||
cache: {
|
||||
...cacheDefaults,
|
||||
|
||||
@@ -63,5 +63,6 @@ export interface BuildContext<T extends Platform> {
|
||||
vcsClient: Client;
|
||||
loggerLevel?: LoggerLevel;
|
||||
repack: boolean;
|
||||
isVerboseLoggingEnabled: boolean;
|
||||
env: Record<string, string>;
|
||||
}
|
||||
@@ -43,6 +43,7 @@ export async function createBuildContextAsync<T extends Platform>({
|
||||
buildLoggerLevel,
|
||||
freezeCredentials,
|
||||
repack,
|
||||
isVerboseLoggingEnabled,
|
||||
env,
|
||||
}: {
|
||||
buildProfileName: string;
|
||||
@@ -65,6 +66,7 @@ export async function createBuildContextAsync<T extends Platform>({
|
||||
buildLoggerLevel?: LoggerLevel;
|
||||
freezeCredentials: boolean;
|
||||
repack: boolean;
|
||||
isVerboseLoggingEnabled: boolean;
|
||||
env: Record<string, string>;
|
||||
}): Promise<BuildContext<T>> {
|
||||
const { exp, projectId } = await getDynamicPrivateProjectConfigAsync({
|
||||
@@ -151,6 +153,7 @@ export async function createBuildContextAsync<T extends Platform>({
|
||||
requiredPackageManager,
|
||||
loggerLevel: buildLoggerLevel,
|
||||
repack,
|
||||
isVerboseLoggingEnabled,
|
||||
env,
|
||||
};
|
||||
if (platform === Platform.ANDROID) {
|
||||
|
||||
@@ -14,7 +14,7 @@ import slash from 'slash';
|
||||
import { IosCredentials, TargetCredentials } from '../../credentials/ios/types';
|
||||
import { IosJobSecretsInput } from '../../graphql/generated';
|
||||
import { getCustomBuildConfigPathForJob } from '../../project/customBuildConfig';
|
||||
import { getUsername } from '../../project/projectUtils';
|
||||
import { getUsernameForBuildMetadataAndBuildJob } from '../../project/projectUtils';
|
||||
import { BuildContext } from '../context';
|
||||
|
||||
interface JobData {
|
||||
@@ -32,7 +32,7 @@ export async function prepareJobAsync(
|
||||
ctx: BuildContext<Platform.IOS>,
|
||||
jobData: JobData
|
||||
): Promise<Ios.Job> {
|
||||
const username = getUsername(ctx.exp, ctx.user);
|
||||
const username = getUsernameForBuildMetadataAndBuildJob(ctx.user);
|
||||
const buildProfile: BuildProfile<Platform.IOS> = ctx.buildProfile;
|
||||
const projectRootDirectory =
|
||||
slash(path.relative(await ctx.vcsClient.getRootPathAsync(), ctx.projectDir)) || '.';
|
||||
@@ -72,7 +72,10 @@ export async function prepareJobAsync(
|
||||
bundler: buildProfile.bundler,
|
||||
cocoapods: buildProfile.cocoapods,
|
||||
fastlane: buildProfile.fastlane,
|
||||
env: buildProfile.env,
|
||||
env: {
|
||||
...buildProfile.env,
|
||||
...(ctx.isVerboseLoggingEnabled ? { EAS_VERBOSE: '1' } : {}),
|
||||
},
|
||||
},
|
||||
cache: {
|
||||
...cacheDefaults,
|
||||
|
||||
@@ -9,7 +9,10 @@ import { maybeResolveVersionsAsync as maybeResolveIosVersionsAsync } from './ios
|
||||
import { LocalBuildMode } from './local';
|
||||
import { BuildDistributionType } from './types';
|
||||
import Log from '../log';
|
||||
import { getUsername, isExpoUpdatesInstalled } from '../project/projectUtils';
|
||||
import {
|
||||
getUsernameForBuildMetadataAndBuildJob,
|
||||
isExpoUpdatesInstalled,
|
||||
} from '../project/projectUtils';
|
||||
import { readChannelSafelyAsync as readAndroidChannelSafelyAsync } from '../update/android/UpdatesModule';
|
||||
import { readChannelSafelyAsync as readIosChannelSafelyAsync } from '../update/ios/UpdatesModule';
|
||||
import { easCliVersion } from '../utils/easCli';
|
||||
@@ -48,7 +51,7 @@ export async function collectMetadataAsync<T extends Platform>(
|
||||
ctx.localBuildOptions.localBuildMode === LocalBuildMode.INTERNAL
|
||||
? false
|
||||
: await ctx.vcsClient.hasUncommittedChangesAsync(),
|
||||
username: getUsername(ctx.exp, ctx.user),
|
||||
username: getUsernameForBuildMetadataAndBuildJob(ctx.user),
|
||||
message: ctx.message,
|
||||
...(ctx.platform === Platform.IOS && {
|
||||
iosEnterpriseProvisioning: resolveIosEnterpriseProvisioning(
|
||||
|
||||
@@ -98,6 +98,7 @@ export interface BuildFlags {
|
||||
buildLoggerLevel?: LoggerLevel;
|
||||
freezeCredentials: boolean;
|
||||
repack: boolean;
|
||||
isVerboseLoggingEnabled?: boolean;
|
||||
}
|
||||
|
||||
export async function runBuildAndSubmitAsync({
|
||||
@@ -229,6 +230,7 @@ export async function runBuildAndSubmitAsync({
|
||||
getDynamicPrivateProjectConfigAsync,
|
||||
customBuildConfigMetadata: customBuildConfigMetadataByPlatform[platform],
|
||||
env,
|
||||
easJsonAccessor,
|
||||
});
|
||||
if (maybeBuild) {
|
||||
startedBuilds.push({ build: maybeBuild, buildProfile });
|
||||
@@ -366,6 +368,7 @@ async function prepareAndStartBuildAsync({
|
||||
getDynamicPrivateProjectConfigAsync,
|
||||
customBuildConfigMetadata,
|
||||
env,
|
||||
easJsonAccessor,
|
||||
}: {
|
||||
projectDir: string;
|
||||
flags: BuildFlags;
|
||||
@@ -378,6 +381,7 @@ async function prepareAndStartBuildAsync({
|
||||
vcsClient: Client;
|
||||
getDynamicPrivateProjectConfigAsync: DynamicConfigContextFn;
|
||||
customBuildConfigMetadata?: CustomBuildConfigMetadata;
|
||||
easJsonAccessor: EasJsonAccessor;
|
||||
env: Env;
|
||||
}): Promise<{ build: BuildFragment | undefined; buildCtx: BuildContext<Platform> }> {
|
||||
const buildCtx = await createBuildContextAsync({
|
||||
@@ -401,6 +405,7 @@ async function prepareAndStartBuildAsync({
|
||||
buildLoggerLevel: flags.buildLoggerLevel ?? (Log.isDebug ? LoggerLevel.DEBUG : undefined),
|
||||
freezeCredentials: flags.freezeCredentials,
|
||||
repack: flags.repack,
|
||||
isVerboseLoggingEnabled: flags.isVerboseLoggingEnabled ?? false,
|
||||
env,
|
||||
});
|
||||
|
||||
@@ -424,8 +429,18 @@ async function prepareAndStartBuildAsync({
|
||||
nonInteractive: flags.nonInteractive,
|
||||
buildProfile,
|
||||
env: buildProfile.profile.env,
|
||||
easJsonAccessor,
|
||||
});
|
||||
if (isUsingEASUpdate(buildCtx.exp, buildCtx.projectId)) {
|
||||
const easJsonUpdateConfig: EasJson['update'] =
|
||||
(await EasJsonUtils.getUpdateConfigAsync(easJsonAccessor)) ?? {};
|
||||
|
||||
if (
|
||||
isUsingEASUpdate(
|
||||
buildCtx.exp,
|
||||
buildCtx.projectId,
|
||||
easJsonUpdateConfig.manifestHostOverride ?? null
|
||||
)
|
||||
) {
|
||||
const doesChannelExist = await doesChannelExistAsync(graphqlClient, {
|
||||
appId: buildCtx.projectId,
|
||||
channelName: buildProfile.profile.channel,
|
||||
@@ -604,6 +619,7 @@ async function validateExpoUpdatesInstalledAsProjectDependencyAsync({
|
||||
nonInteractive,
|
||||
sdkVersion,
|
||||
env,
|
||||
easJsonAccessor,
|
||||
}: {
|
||||
exp: ExpoConfig;
|
||||
projectId: string;
|
||||
@@ -613,6 +629,7 @@ async function validateExpoUpdatesInstalledAsProjectDependencyAsync({
|
||||
nonInteractive: boolean;
|
||||
sdkVersion?: string;
|
||||
env: Env | undefined;
|
||||
easJsonAccessor: EasJsonAccessor;
|
||||
}): Promise<void> {
|
||||
if (isExpoUpdatesInstalledOrAvailable(projectDir, sdkVersion)) {
|
||||
return;
|
||||
@@ -634,6 +651,9 @@ async function validateExpoUpdatesInstalledAsProjectDependencyAsync({
|
||||
message: `Would you like to install the "expo-updates" package and configure EAS Update now?`,
|
||||
});
|
||||
if (installExpoUpdates) {
|
||||
const easJsonUpdateConfig: EasJson['update'] =
|
||||
(await EasJsonUtils.getUpdateConfigAsync(easJsonAccessor)) ?? {};
|
||||
|
||||
await ensureEASUpdateIsConfiguredAsync({
|
||||
exp,
|
||||
projectId,
|
||||
@@ -641,6 +661,7 @@ async function validateExpoUpdatesInstalledAsProjectDependencyAsync({
|
||||
platform: RequestedPlatform.All,
|
||||
vcsClient,
|
||||
env,
|
||||
manifestHostOverride: easJsonUpdateConfig.manifestHostOverride ?? null,
|
||||
});
|
||||
Log.withTick('Installed expo-updates and configured EAS Update.');
|
||||
throw new Error('Command must be re-run to pick up new updates configuration.');
|
||||
|
||||
@@ -180,7 +180,7 @@ export async function validateOrSetProjectIdAsync({
|
||||
|
||||
Log.warn('EAS project not configured.');
|
||||
|
||||
const getAccountNameForEASProjectSync = (exp: ExpoConfig, user: Actor): string => {
|
||||
const getDefaultAccountNameForEASProject = (exp: ExpoConfig, user: Actor): string => {
|
||||
if (exp.owner) {
|
||||
return exp.owner;
|
||||
}
|
||||
@@ -191,7 +191,7 @@ export async function validateOrSetProjectIdAsync({
|
||||
return user.username;
|
||||
case 'Robot':
|
||||
throw new Error(
|
||||
'The "owner" manifest property is required when using robot users. See: https://docs.expo.dev/versions/latest/config/app/#owner'
|
||||
'Must configure EAS project by running "eas init" before using a robot user to manage the project.'
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -199,7 +199,7 @@ export async function validateOrSetProjectIdAsync({
|
||||
const projectId = await fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync(
|
||||
graphqlClient,
|
||||
{
|
||||
accountName: getAccountNameForEASProjectSync(exp, actor),
|
||||
accountName: getDefaultAccountNameForEASProject(exp, actor),
|
||||
projectName: exp.slug,
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Platform, Workflow } from '@expo/eas-build-job';
|
||||
import { EasJson, EasJsonAccessor, EasJsonUtils } from '@expo/eas-json';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
|
||||
@@ -66,8 +67,13 @@ export default class BuildConfigure extends EasCommand {
|
||||
nonInteractive: false,
|
||||
vcsClient,
|
||||
});
|
||||
if (didCreateEasJson && isUsingEASUpdate(exp, projectId)) {
|
||||
await ensureEASUpdateIsConfiguredInEasJsonAsync(projectDir);
|
||||
if (didCreateEasJson) {
|
||||
const easJsonAccessor = EasJsonAccessor.fromProjectPath(projectDir);
|
||||
const easJsonUpdateConfig: EasJson['update'] =
|
||||
(await EasJsonUtils.getUpdateConfigAsync(easJsonAccessor)) ?? {};
|
||||
if (isUsingEASUpdate(exp, projectId, easJsonUpdateConfig.manifestHostOverride ?? null)) {
|
||||
await ensureEASUpdateIsConfiguredInEasJsonAsync(projectDir);
|
||||
}
|
||||
}
|
||||
|
||||
// configure expo-updates
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
import { Platform } from '@expo/eas-build-job';
|
||||
import { Errors, Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
import { pathExists } from 'fs-extra';
|
||||
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
|
||||
import { EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
|
||||
import { AppPlatform, BuildFragment, BuildStatus, DistributionType } from '../../graphql/generated';
|
||||
import { BuildQuery } from '../../graphql/queries/BuildQuery';
|
||||
import { toAppPlatform } from '../../graphql/types/AppPlatform';
|
||||
import Log from '../../log';
|
||||
import { promptAsync } from '../../prompts';
|
||||
import { getEasBuildRunCachedAppPath } from '../../run/run';
|
||||
import { downloadAndMaybeExtractAppAsync } from '../../utils/download';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
|
||||
export default class Download extends EasCommand {
|
||||
static override description = 'download simulator/emulator builds for a given fingerprint hash';
|
||||
|
||||
static override flags = {
|
||||
fingerprint: Flags.string({
|
||||
description: 'Fingerprint hash of the build to download',
|
||||
required: true,
|
||||
}),
|
||||
platform: Flags.enum<Platform.IOS | Platform.ANDROID>({
|
||||
char: 'p',
|
||||
options: [Platform.IOS, Platform.ANDROID],
|
||||
}),
|
||||
'dev-client': Flags.boolean({
|
||||
description: 'Filter only dev-client builds.',
|
||||
allowNo: true,
|
||||
}),
|
||||
...EasNonInteractiveAndJsonFlags,
|
||||
};
|
||||
|
||||
static override contextDefinition = {
|
||||
...this.ContextOptions.LoggedIn,
|
||||
...this.ContextOptions.ProjectId,
|
||||
};
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const {
|
||||
flags: {
|
||||
json: jsonFlag,
|
||||
platform,
|
||||
fingerprint,
|
||||
'dev-client': developmentClient,
|
||||
'non-interactive': nonInteractive,
|
||||
},
|
||||
} = await this.parse(Download);
|
||||
|
||||
const {
|
||||
loggedIn: { graphqlClient },
|
||||
projectId,
|
||||
} = await this.getContextAsync(Download, {
|
||||
nonInteractive,
|
||||
});
|
||||
|
||||
if (jsonFlag) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
|
||||
const selectedPlatform = await resolvePlatformAsync({ nonInteractive, platform });
|
||||
const build = await this.getBuildAsync({
|
||||
graphqlClient,
|
||||
projectId,
|
||||
platform: selectedPlatform,
|
||||
fingerprintHash: fingerprint,
|
||||
developmentClient,
|
||||
});
|
||||
const buildArtifactPath = await this.getPathToBuildArtifactAsync(build, selectedPlatform);
|
||||
if (jsonFlag) {
|
||||
const jsonResults = { path: buildArtifactPath };
|
||||
printJsonOnlyOutput(jsonResults);
|
||||
} else {
|
||||
Log.log(`Build downloaded to ${chalk.bold(buildArtifactPath)}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async getBuildAsync({
|
||||
graphqlClient,
|
||||
projectId,
|
||||
platform,
|
||||
fingerprintHash,
|
||||
developmentClient,
|
||||
}: {
|
||||
graphqlClient: ExpoGraphqlClient;
|
||||
projectId: string;
|
||||
platform: AppPlatform;
|
||||
fingerprintHash: string;
|
||||
developmentClient: boolean;
|
||||
}): Promise<BuildFragment> {
|
||||
const builds = await BuildQuery.viewBuildsOnAppAsync(graphqlClient, {
|
||||
appId: projectId,
|
||||
filter: {
|
||||
platform,
|
||||
fingerprintHash,
|
||||
status: BuildStatus.Finished,
|
||||
simulator: platform === AppPlatform.Ios ? true : undefined,
|
||||
distribution: platform === AppPlatform.Android ? DistributionType.Internal : undefined,
|
||||
developmentClient,
|
||||
},
|
||||
offset: 0,
|
||||
limit: 1,
|
||||
});
|
||||
if (builds.length === 0) {
|
||||
throw new Errors.CLIError(
|
||||
`No builds available for ${platform} with fingerprint hash ${fingerprintHash}`
|
||||
);
|
||||
}
|
||||
|
||||
Log.succeed(`🎯 Found successful build with matching fingerprint on EAS servers.`);
|
||||
return builds[0];
|
||||
}
|
||||
|
||||
async getPathToBuildArtifactAsync(build: BuildFragment, platform: AppPlatform): Promise<string> {
|
||||
const cachedBuildArtifactPath = getEasBuildRunCachedAppPath(
|
||||
build.project.id,
|
||||
build.id,
|
||||
platform
|
||||
);
|
||||
if (await pathExists(cachedBuildArtifactPath)) {
|
||||
Log.newLine();
|
||||
Log.log(`Using cached build...`);
|
||||
return cachedBuildArtifactPath;
|
||||
}
|
||||
|
||||
if (!build.artifacts?.applicationArchiveUrl) {
|
||||
throw new Error('Build does not have an application archive url');
|
||||
}
|
||||
|
||||
return await downloadAndMaybeExtractAppAsync(
|
||||
build.artifacts.applicationArchiveUrl,
|
||||
platform,
|
||||
cachedBuildArtifactPath
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function resolvePlatformAsync({
|
||||
nonInteractive,
|
||||
platform,
|
||||
}: {
|
||||
nonInteractive: boolean;
|
||||
platform?: Platform;
|
||||
}): Promise<AppPlatform> {
|
||||
if (nonInteractive && !platform) {
|
||||
throw new Error('Platform must be provided in non-interactive mode');
|
||||
}
|
||||
|
||||
if (platform) {
|
||||
return toAppPlatform(platform);
|
||||
}
|
||||
|
||||
const { selectedPlatform } = await promptAsync({
|
||||
type: 'select',
|
||||
message: 'Select platform',
|
||||
name: 'selectedPlatform',
|
||||
choices: [
|
||||
{ title: 'Android', value: AppPlatform.Android },
|
||||
{ title: 'iOS', value: AppPlatform.Ios },
|
||||
],
|
||||
});
|
||||
return selectedPlatform;
|
||||
}
|
||||
@@ -37,6 +37,7 @@ interface RawBuildFlags {
|
||||
message?: string;
|
||||
'build-logger-level'?: LoggerLevel;
|
||||
'freeze-credentials': boolean;
|
||||
'verbose-logs'?: boolean;
|
||||
repack: boolean;
|
||||
}
|
||||
|
||||
@@ -118,6 +119,10 @@ export default class Build extends EasCommand {
|
||||
hidden: true,
|
||||
description: 'Use the golden dev client build repack flow as it works for onboarding',
|
||||
}),
|
||||
'verbose-logs': Flags.boolean({
|
||||
default: false,
|
||||
description: 'Use verbose logs for the build process',
|
||||
}),
|
||||
...EasNonInteractiveAndJsonFlags,
|
||||
};
|
||||
|
||||
@@ -238,6 +243,7 @@ export default class Build extends EasCommand {
|
||||
message,
|
||||
buildLoggerLevel: flags['build-logger-level'],
|
||||
freezeCredentials: flags['freeze-credentials'],
|
||||
isVerboseLoggingEnabled: flags['verbose-logs'],
|
||||
repack: flags.repack,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -401,7 +401,7 @@ async function configureProjectFromBareDefaultExpoTemplateAsync({
|
||||
const bundleIdentifier = `com.${userPrefix}${stripInvalidCharactersForBundleIdentifier(
|
||||
app.ownerAccount.name
|
||||
)}.${slugPrefix}${stripInvalidCharactersForBundleIdentifier(app.slug)}`;
|
||||
const updateUrl = getEASUpdateURL(app.id);
|
||||
const updateUrl = getEASUpdateURL(app.id, /* manifestHostOverride */ null);
|
||||
|
||||
const easBuildGitHubConfig = {
|
||||
android: {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { EasJson, EasJsonAccessor, EasJsonUtils } from '@expo/eas-json';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
|
||||
@@ -47,6 +48,10 @@ export default class UpdateConfigure extends EasCommand {
|
||||
|
||||
await vcsClient.ensureRepoExistsAsync();
|
||||
|
||||
const easJsonAccessor = EasJsonAccessor.fromProjectPath(projectDir);
|
||||
const easJsonUpdateConfig: EasJson['update'] =
|
||||
(await EasJsonUtils.getUpdateConfigAsync(easJsonAccessor)) ?? {};
|
||||
|
||||
await ensureEASUpdateIsConfiguredAsync({
|
||||
exp,
|
||||
projectId,
|
||||
@@ -55,6 +60,7 @@ export default class UpdateConfigure extends EasCommand {
|
||||
vcsClient,
|
||||
env: undefined,
|
||||
forceNativeConfigSync: true,
|
||||
manifestHostOverride: easJsonUpdateConfig.manifestHostOverride ?? null,
|
||||
});
|
||||
|
||||
await ensureEASUpdateIsConfiguredInEasJsonAsync(projectDir);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Workflow } from '@expo/eas-build-job';
|
||||
import { EasJson, EasJsonAccessor, EasJsonUtils } from '@expo/eas-json';
|
||||
import { Errors, Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
import nullthrows from 'nullthrows';
|
||||
@@ -13,6 +14,7 @@ import { EasNonInteractiveAndJsonFlags, EasUpdateEnvironmentFlag } from '../../c
|
||||
import { getPaginatedQueryOptions } from '../../commandUtils/pagination';
|
||||
import fetch from '../../fetch';
|
||||
import {
|
||||
AssetMapSourceInput,
|
||||
EnvironmentVariableEnvironment,
|
||||
FingerprintInfoGroup as GraphqlFingerprintInfoGroup,
|
||||
PublishUpdateGroupInput,
|
||||
@@ -26,6 +28,7 @@ import { AppQuery } from '../../graphql/queries/AppQuery';
|
||||
import Log, { learnMore, link } from '../../log';
|
||||
import { ora } from '../../ora';
|
||||
import { RequestedPlatform } from '../../platform';
|
||||
import { maybeUploadAssetMapAsync } from '../../project/maybeUploadAssetMapAsync';
|
||||
import { maybeUploadFingerprintAsync } from '../../project/maybeUploadFingerprintAsync';
|
||||
import { getOwnerAccountForProjectIdAsync } from '../../project/projectUtils';
|
||||
import {
|
||||
@@ -209,6 +212,10 @@ export default class UpdatePublish extends EasCommand {
|
||||
|
||||
await maybeWarnAboutEasOutagesAsync(graphqlClient, [StatuspageServiceName.EasUpdate]);
|
||||
|
||||
const easJsonAccessor = EasJsonAccessor.fromProjectPath(projectDir);
|
||||
const easJsonUpdateConfig: EasJson['update'] =
|
||||
(await EasJsonUtils.getUpdateConfigAsync(easJsonAccessor)) ?? {};
|
||||
|
||||
await ensureEASUpdateIsConfiguredAsync({
|
||||
exp: expPossiblyWithoutEasUpdateConfigured,
|
||||
platform: requestedPlatform,
|
||||
@@ -216,6 +223,7 @@ export default class UpdatePublish extends EasCommand {
|
||||
projectId,
|
||||
vcsClient,
|
||||
env: undefined,
|
||||
manifestHostOverride: easJsonUpdateConfig.manifestHostOverride ?? null,
|
||||
});
|
||||
|
||||
const { exp } = await getDynamicPublicProjectConfigAsync();
|
||||
@@ -271,9 +279,14 @@ export default class UpdatePublish extends EasCommand {
|
||||
let uploadedAssetCount = 0;
|
||||
let assetLimitPerUpdateGroup = 0;
|
||||
let realizedPlatforms: UpdatePublishPlatform[] = [];
|
||||
let assetMapSource: AssetMapSourceInput | null = null;
|
||||
|
||||
try {
|
||||
const collectedAssets = await collectAssetsAsync(distRoot);
|
||||
const [collectedAssets, maybeAssetMapSource] = await Promise.all([
|
||||
collectAssetsAsync(distRoot),
|
||||
maybeUploadAssetMapAsync(distRoot, graphqlClient),
|
||||
]);
|
||||
assetMapSource = maybeAssetMapSource;
|
||||
const assets = filterCollectedAssetsByRequestedPlatforms(collectedAssets, requestedPlatform);
|
||||
realizedPlatforms = Object.keys(assets) as UpdatePublishPlatform[];
|
||||
|
||||
@@ -484,17 +497,24 @@ export default class UpdatePublish extends EasCommand {
|
||||
{} as GraphqlFingerprintInfoGroup
|
||||
);
|
||||
|
||||
const assetMapGroup = assetMapSource
|
||||
? Object.fromEntries(platforms.map(platform => [platform, assetMapSource]))
|
||||
: null;
|
||||
|
||||
return {
|
||||
branchId: branch.id,
|
||||
updateInfoGroup: localUpdateInfoGroup,
|
||||
rolloutInfoGroup: localRolloutInfoGroup,
|
||||
fingerprintInfoGroup: transformedFingerprintInfoGroup,
|
||||
assetMapGroup,
|
||||
runtimeVersion,
|
||||
message: updateMessage,
|
||||
gitCommitHash,
|
||||
isGitWorkingTreeDirty,
|
||||
awaitingCodeSigningInfo: !!codeSigningInfo,
|
||||
environment: environment ?? null,
|
||||
manifestHostOverride: easJsonUpdateConfig.manifestHostOverride ?? null,
|
||||
assetHostOverride: easJsonUpdateConfig.assetHostOverride ?? null,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
@@ -31,6 +31,7 @@ type UpdateRepublishRawFlags = {
|
||||
'private-key-path'?: string;
|
||||
'non-interactive': boolean;
|
||||
json?: boolean;
|
||||
'rollout-percentage'?: number;
|
||||
};
|
||||
|
||||
type UpdateRepublishFlags = {
|
||||
@@ -44,6 +45,7 @@ type UpdateRepublishFlags = {
|
||||
privateKeyPath?: string;
|
||||
nonInteractive: boolean;
|
||||
json: boolean;
|
||||
rolloutPercentage?: number;
|
||||
};
|
||||
|
||||
export default class UpdateRepublish extends EasCommand {
|
||||
@@ -86,6 +88,12 @@ export default class UpdateRepublish extends EasCommand {
|
||||
description: `File containing the PEM-encoded private key corresponding to the certificate in expo-updates' configuration. Defaults to a file named "private-key.pem" in the certificate's directory. Only relevant if you are using code signing: https://docs.expo.dev/eas-update/code-signing/`,
|
||||
required: false,
|
||||
}),
|
||||
'rollout-percentage': Flags.integer({
|
||||
description: `Percentage of users this update should be immediately available to. Users not in the rollout will be served the previous latest update on the branch, even if that update is itself being rolled out. The specified number must be an integer between 1 and 100. When not specified, this defaults to 100.`,
|
||||
required: false,
|
||||
min: 0,
|
||||
max: 100,
|
||||
}),
|
||||
...EasNonInteractiveAndJsonFlags,
|
||||
};
|
||||
|
||||
@@ -163,6 +171,7 @@ export default class UpdateRepublish extends EasCommand {
|
||||
updateMessage,
|
||||
codeSigningInfo,
|
||||
json: flags.json,
|
||||
rolloutPercentage: flags.rolloutPercentage,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -191,6 +200,7 @@ export default class UpdateRepublish extends EasCommand {
|
||||
platform,
|
||||
updateMessage: rawFlags.message,
|
||||
privateKeyPath,
|
||||
rolloutPercentage: rawFlags['rollout-percentage'],
|
||||
json: rawFlags.json ?? false,
|
||||
nonInteractive,
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Platform as PublishPlatform } from '@expo/config';
|
||||
import { EasJson, EasJsonAccessor, EasJsonUtils } from '@expo/eas-json';
|
||||
import { Errors, Flags } from '@oclif/core';
|
||||
import nullthrows from 'nullthrows';
|
||||
|
||||
@@ -148,6 +149,10 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
|
||||
|
||||
await maybeWarnAboutEasOutagesAsync(graphqlClient, [StatuspageServiceName.EasUpdate]);
|
||||
|
||||
const easJsonAccessor = EasJsonAccessor.fromProjectPath(projectDir);
|
||||
const easJsonUpdateConfig: EasJson['update'] =
|
||||
(await EasJsonUtils.getUpdateConfigAsync(easJsonAccessor)) ?? {};
|
||||
|
||||
await ensureEASUpdateIsConfiguredAsync({
|
||||
exp: expPossiblyWithoutEasUpdateConfigured,
|
||||
platform: platformFlag,
|
||||
@@ -155,6 +160,7 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
|
||||
projectId,
|
||||
vcsClient,
|
||||
env: undefined,
|
||||
manifestHostOverride: easJsonUpdateConfig.manifestHostOverride ?? null,
|
||||
});
|
||||
|
||||
// check that the expo-updates package version supports roll back to embedded
|
||||
|
||||
@@ -11,8 +11,9 @@ import { v4 as uuidv4 } from 'uuid';
|
||||
import { getBuildLogsUrl } from '../build/utils/url';
|
||||
import EasCommand from '../commandUtils/EasCommand';
|
||||
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
|
||||
import { EASNonInteractiveFlag } from '../commandUtils/flags';
|
||||
import { EasNonInteractiveAndJsonFlags } from '../commandUtils/flags';
|
||||
import {
|
||||
BuildMetadataInput,
|
||||
DistributionType,
|
||||
LocalBuildArchiveSourceType,
|
||||
UploadSessionType,
|
||||
@@ -24,7 +25,10 @@ import Log from '../log';
|
||||
import { promptAsync } from '../prompts';
|
||||
import * as xcode from '../run/ios/xcode';
|
||||
import { uploadFileAtPathToGCSAsync } from '../uploads';
|
||||
import { fromNow } from '../utils/date';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../utils/json';
|
||||
import { getTmpDirectory } from '../utils/paths';
|
||||
import { parseBinaryPlistBuffer } from '../utils/plist';
|
||||
import { createProgressTracker } from '../utils/progress';
|
||||
|
||||
export default class BuildUpload extends EasCommand {
|
||||
@@ -42,7 +46,7 @@ export default class BuildUpload extends EasCommand {
|
||||
fingerprint: Flags.string({
|
||||
description: 'Fingerprint hash of the local build',
|
||||
}),
|
||||
...EASNonInteractiveFlag,
|
||||
...EasNonInteractiveAndJsonFlags,
|
||||
};
|
||||
|
||||
static override contextDefinition = {
|
||||
@@ -52,21 +56,35 @@ export default class BuildUpload extends EasCommand {
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { flags } = await this.parse(BuildUpload);
|
||||
const { 'build-path': buildPath, fingerprint: manualFingerprintHash } = flags;
|
||||
const {
|
||||
'build-path': buildPath,
|
||||
fingerprint: manualFingerprintHash,
|
||||
json: jsonFlag,
|
||||
'non-interactive': nonInteractive,
|
||||
} = flags;
|
||||
const {
|
||||
projectId,
|
||||
loggedIn: { graphqlClient },
|
||||
} = await this.getContextAsync(BuildUpload, {
|
||||
nonInteractive: false,
|
||||
nonInteractive,
|
||||
});
|
||||
|
||||
const platform = await this.selectPlatformAsync(flags.platform);
|
||||
const localBuildPath = await resolveLocalBuildPathAsync(platform, buildPath);
|
||||
if (jsonFlag) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
|
||||
const platform = await this.selectPlatformAsync({ platform: flags.platform, nonInteractive });
|
||||
const localBuildPath = await resolveLocalBuildPathAsync({
|
||||
platform,
|
||||
inputBuildPath: buildPath,
|
||||
nonInteractive,
|
||||
});
|
||||
|
||||
const {
|
||||
fingerprintHash: buildFingerprintHash,
|
||||
developmentClient,
|
||||
simulator,
|
||||
...otherMetadata
|
||||
} = await extractAppMetadataAsync(localBuildPath, platform);
|
||||
|
||||
let fingerprint = manualFingerprintHash ?? buildFingerprintHash;
|
||||
@@ -74,7 +92,8 @@ export default class BuildUpload extends EasCommand {
|
||||
if (
|
||||
manualFingerprintHash &&
|
||||
buildFingerprintHash &&
|
||||
manualFingerprintHash !== buildFingerprintHash
|
||||
manualFingerprintHash !== buildFingerprintHash &&
|
||||
!nonInteractive
|
||||
) {
|
||||
const selectedAnswer = await promptAsync({
|
||||
name: 'fingerprint',
|
||||
@@ -104,13 +123,33 @@ export default class BuildUpload extends EasCommand {
|
||||
projectId,
|
||||
{ platform: toAppPlatform(platform), simulator },
|
||||
{ type: LocalBuildArchiveSourceType.Gcs, bucketKey },
|
||||
{ distribution: DistributionType.Internal, fingerprintHash: fingerprint, developmentClient }
|
||||
{
|
||||
distribution: DistributionType.Internal,
|
||||
fingerprintHash: fingerprint,
|
||||
developmentClient,
|
||||
...otherMetadata,
|
||||
}
|
||||
);
|
||||
|
||||
Log.withTick(`Here is a sharable link of your build: ${getBuildLogsUrl(build)}`);
|
||||
if (jsonFlag) {
|
||||
printJsonOnlyOutput({ url: getBuildLogsUrl(build) });
|
||||
return;
|
||||
}
|
||||
|
||||
Log.withTick(`Shareable link to the build: ${getBuildLogsUrl(build)}`);
|
||||
}
|
||||
|
||||
private async selectPlatformAsync(platform?: Platform): Promise<Platform> {
|
||||
private async selectPlatformAsync({
|
||||
nonInteractive,
|
||||
platform,
|
||||
}: {
|
||||
nonInteractive: boolean;
|
||||
platform?: Platform;
|
||||
}): Promise<Platform> {
|
||||
if (nonInteractive && !platform) {
|
||||
throw new Error('Platform must be provided in non-interactive mode');
|
||||
}
|
||||
|
||||
if (platform) {
|
||||
return platform;
|
||||
}
|
||||
@@ -127,10 +166,15 @@ export default class BuildUpload extends EasCommand {
|
||||
}
|
||||
}
|
||||
|
||||
async function resolveLocalBuildPathAsync(
|
||||
platform: Platform,
|
||||
inputBuildPath?: string
|
||||
): Promise<string> {
|
||||
async function resolveLocalBuildPathAsync({
|
||||
platform,
|
||||
inputBuildPath,
|
||||
nonInteractive,
|
||||
}: {
|
||||
platform: Platform;
|
||||
inputBuildPath?: string;
|
||||
nonInteractive: boolean;
|
||||
}): Promise<string> {
|
||||
const rootDir = process.cwd();
|
||||
let applicationArchivePatternOrPath: string[] = [];
|
||||
|
||||
@@ -156,7 +200,7 @@ async function resolveLocalBuildPathAsync(
|
||||
patternOrPathArray: applicationArchivePatternOrPath,
|
||||
});
|
||||
|
||||
if (applicationArchives.length === 0 && !inputBuildPath) {
|
||||
if (applicationArchives.length === 0 && !nonInteractive && !inputBuildPath) {
|
||||
Log.warn(`No application archives found at ${applicationArchivePatternOrPath}.`);
|
||||
const { path } = await promptAsync({
|
||||
type: 'text',
|
||||
@@ -175,18 +219,33 @@ async function resolveLocalBuildPathAsync(
|
||||
}
|
||||
|
||||
if (applicationArchives.length > 1) {
|
||||
const { path } = await promptAsync({
|
||||
// sort by modification time
|
||||
const applicationArchivesInfo = await Promise.all(
|
||||
applicationArchives.map(async archivePath => ({
|
||||
path: archivePath,
|
||||
stat: await fs.stat(archivePath),
|
||||
}))
|
||||
);
|
||||
applicationArchivesInfo.sort((a, b) => b.stat.mtimeMs - a.stat.mtimeMs);
|
||||
|
||||
if (nonInteractive) {
|
||||
return applicationArchivesInfo[0].path;
|
||||
}
|
||||
|
||||
const { selectedPath } = await promptAsync({
|
||||
type: 'select',
|
||||
name: 'path',
|
||||
name: 'selectedPath',
|
||||
message: 'Found multiple application archives. Select one:',
|
||||
choices: applicationArchives.map(archivePath => {
|
||||
choices: applicationArchivesInfo.map(archive => {
|
||||
return {
|
||||
title: archivePath,
|
||||
value: archivePath,
|
||||
title: `${
|
||||
archive.path.startsWith(rootDir) ? path.relative(rootDir, archive.path) : archive.path
|
||||
} (${fromNow(archive.stat.mtime)} ago)`,
|
||||
value: archive.path,
|
||||
};
|
||||
}),
|
||||
});
|
||||
return path;
|
||||
return selectedPath;
|
||||
}
|
||||
|
||||
throw new Error(`Found no application archives at ${inputBuildPath}.`);
|
||||
@@ -252,19 +311,33 @@ async function uploadAppArchiveAsync(
|
||||
return bucketKey;
|
||||
}
|
||||
|
||||
type AppMetadata = {
|
||||
fingerprintHash?: string;
|
||||
developmentClient: boolean;
|
||||
function getInfoPlistMetadata(infoPlist: any): {
|
||||
appName?: string;
|
||||
appIdentifier?: string;
|
||||
simulator: boolean;
|
||||
};
|
||||
} {
|
||||
const appName = infoPlist?.CFBundleDisplayName ?? infoPlist?.CFBundleName;
|
||||
const appIdentifier = infoPlist?.CFBundleIdentifier;
|
||||
const simulator = infoPlist?.DTPlatformName?.includes('simulator');
|
||||
|
||||
return {
|
||||
appName,
|
||||
appIdentifier,
|
||||
simulator,
|
||||
};
|
||||
}
|
||||
|
||||
async function extractAppMetadataAsync(
|
||||
buildPath: string,
|
||||
platform: Platform
|
||||
): Promise<AppMetadata> {
|
||||
): Promise<{ developmentClient: boolean; simulator: boolean } & BuildMetadataInput> {
|
||||
let developmentClient = false;
|
||||
let fingerprintHash: string | undefined;
|
||||
const simulator = platform === Platform.IOS;
|
||||
|
||||
// By default, we assume the iOS apps are for simulators
|
||||
let simulator = platform === Platform.IOS;
|
||||
let appName: string | undefined;
|
||||
let appIdentifier: string | undefined;
|
||||
|
||||
const basePath = platform === Platform.ANDROID ? 'assets/' : buildPath;
|
||||
const fingerprintFilePath =
|
||||
@@ -289,14 +362,51 @@ async function extractAppMetadataAsync(
|
||||
}
|
||||
} else if (buildExtension === '.app') {
|
||||
developmentClient = await fs.exists(path.join(basePath, devMenuBundlePath));
|
||||
if (await fs.exists(path.join(basePath, 'Info.plist'))) {
|
||||
const infoPlistBuffer = await fs.readFile(path.join(basePath, 'Info.plist'));
|
||||
const infoPlist = parseBinaryPlistBuffer(infoPlistBuffer);
|
||||
({ simulator, appIdentifier, appName } = getInfoPlistMetadata(infoPlist));
|
||||
}
|
||||
|
||||
if (await fs.exists(path.join(basePath, fingerprintFilePath))) {
|
||||
fingerprintHash = await fs.readFile(path.join(basePath, fingerprintFilePath), 'utf8');
|
||||
}
|
||||
} else if (buildExtension === '.ipa') {
|
||||
const zip = new StreamZip.async({ file: buildPath });
|
||||
try {
|
||||
const entries = await zip.entries();
|
||||
const entriesKeys = Object.keys(entries);
|
||||
|
||||
await Promise.all(
|
||||
entriesKeys.map(async path => {
|
||||
const infoPlistRegex = /^Payload\/[^/]+\.app\/Info\.plist$/;
|
||||
if (infoPlistRegex.test(path)) {
|
||||
const infoPlistBuffer = await zip.entryData(entries[path]);
|
||||
const infoPlist = parseBinaryPlistBuffer(infoPlistBuffer);
|
||||
({ simulator, appIdentifier, appName } = getInfoPlistMetadata(infoPlist));
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.includes('/EXDevMenu.bundle')) {
|
||||
developmentClient = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.includes('EXUpdates.bundle/fingerprint')) {
|
||||
fingerprintHash = (await zip.entryData(entries[path])).toString('utf-8');
|
||||
}
|
||||
})
|
||||
);
|
||||
} catch (err) {
|
||||
Log.error(`Error reading ${buildExtension}: ${err}`);
|
||||
} finally {
|
||||
await zip.close();
|
||||
}
|
||||
} else {
|
||||
// Use tar to list files in the archive
|
||||
try {
|
||||
let fingerprintHashPromise: Promise<string> | undefined;
|
||||
let infoPlistPromise: Promise<Buffer> | undefined;
|
||||
await tar.list({
|
||||
file: buildPath,
|
||||
// eslint-disable-next-line async-protect/async-suffix
|
||||
@@ -317,11 +427,29 @@ async function extractAppMetadataAsync(
|
||||
}
|
||||
});
|
||||
}
|
||||
if (entry.path.endsWith('Info.plist')) {
|
||||
infoPlistPromise = new Promise<Buffer>(async (resolve, reject) => {
|
||||
try {
|
||||
const chunks: Buffer[] = [];
|
||||
for await (const chunk of entry) {
|
||||
chunks.push(chunk);
|
||||
}
|
||||
const content = Buffer.concat(chunks);
|
||||
resolve(content);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
if (fingerprintHashPromise !== undefined) {
|
||||
fingerprintHash = await fingerprintHashPromise;
|
||||
}
|
||||
if (infoPlistPromise !== undefined) {
|
||||
const infoPlist = parseBinaryPlistBuffer(await infoPlistPromise);
|
||||
({ simulator, appIdentifier, appName } = getInfoPlistMetadata(infoPlist));
|
||||
}
|
||||
} catch (err) {
|
||||
Log.error(`Error reading ${buildExtension}: ${err}`);
|
||||
}
|
||||
@@ -331,5 +459,7 @@ async function extractAppMetadataAsync(
|
||||
developmentClient,
|
||||
fingerprintHash,
|
||||
simulator,
|
||||
appName,
|
||||
appIdentifier,
|
||||
};
|
||||
}
|
||||
@@ -1,25 +1,48 @@
|
||||
import { Flags } from '@oclif/core';
|
||||
import { CombinedError } from '@urql/core';
|
||||
import * as path from 'node:path';
|
||||
|
||||
import { getWorkflowRunUrl } from '../../build/utils/url';
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import { EASNonInteractiveFlag } from '../../commandUtils/flags';
|
||||
import { WorkflowProjectSourceType } from '../../graphql/generated';
|
||||
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
|
||||
import { EASNonInteractiveFlag, EasJsonOnlyFlag } from '../../commandUtils/flags';
|
||||
import {
|
||||
WorkflowProjectSourceType,
|
||||
WorkflowRunByIdQuery,
|
||||
WorkflowRunStatus,
|
||||
} from '../../graphql/generated';
|
||||
import { WorkflowRevisionMutation } from '../../graphql/mutations/WorkflowRevisionMutation';
|
||||
import { WorkflowRunMutation } from '../../graphql/mutations/WorkflowRunMutation';
|
||||
import { WorkflowRunQuery } from '../../graphql/queries/WorkflowRunQuery';
|
||||
import Log, { link } from '../../log';
|
||||
import { ora } from '../../ora';
|
||||
import { getOwnerAccountForProjectIdAsync } from '../../project/projectUtils';
|
||||
import { uploadAccountScopedFileAsync } from '../../project/uploadAccountScopedFileAsync';
|
||||
import { uploadAccountScopedProjectSourceAsync } from '../../project/uploadAccountScopedProjectSourceAsync';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
import { sleepAsync } from '../../utils/promise';
|
||||
import { WorkflowFile } from '../../utils/workflowFile';
|
||||
|
||||
const EXIT_CODES = {
|
||||
WORKFLOW_FAILED: 11,
|
||||
WORKFLOW_CANCELED: 12,
|
||||
WAIT_ABORTED: 13,
|
||||
};
|
||||
|
||||
export default class WorkflowRun extends EasCommand {
|
||||
static override description = 'Run an EAS workflow';
|
||||
static override description = 'run an EAS workflow';
|
||||
|
||||
static override args = [{ name: 'file', description: 'Path to the workflow file to run' }];
|
||||
|
||||
static override flags = {
|
||||
...EASNonInteractiveFlag,
|
||||
wait: Flags.boolean({
|
||||
default: false,
|
||||
allowNo: true,
|
||||
description: 'Exit codes: 0 = success, 11 = failure, 12 = canceled, 13 = wait aborted.',
|
||||
summary: 'Wait for workflow run to complete',
|
||||
}),
|
||||
...EasJsonOnlyFlag,
|
||||
};
|
||||
|
||||
static override contextDefinition = {
|
||||
@@ -32,6 +55,10 @@ export default class WorkflowRun extends EasCommand {
|
||||
async runAsync(): Promise<void> {
|
||||
const { flags, args } = await this.parse(WorkflowRun);
|
||||
|
||||
if (flags.json) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
|
||||
const {
|
||||
getDynamicPrivateProjectConfigAsync,
|
||||
loggedIn: { graphqlClient },
|
||||
@@ -107,36 +134,120 @@ export default class WorkflowRun extends EasCommand {
|
||||
throw err;
|
||||
}
|
||||
|
||||
let workflowRunId: string;
|
||||
|
||||
try {
|
||||
const { id: workflowRunId } = await WorkflowRunMutation.createWorkflowRunAsync(
|
||||
graphqlClient,
|
||||
{
|
||||
appId: projectId,
|
||||
workflowRevisionInput: {
|
||||
fileName: path.basename(args.file),
|
||||
yamlConfig,
|
||||
({ id: workflowRunId } = await WorkflowRunMutation.createWorkflowRunAsync(graphqlClient, {
|
||||
appId: projectId,
|
||||
workflowRevisionInput: {
|
||||
fileName: path.basename(args.file),
|
||||
yamlConfig,
|
||||
},
|
||||
workflowRunInput: {
|
||||
projectSource: {
|
||||
type: WorkflowProjectSourceType.Gcs,
|
||||
projectArchiveBucketKey,
|
||||
easJsonBucketKey,
|
||||
packageJsonBucketKey,
|
||||
},
|
||||
workflowRunInput: {
|
||||
projectSource: {
|
||||
type: WorkflowProjectSourceType.Gcs,
|
||||
projectArchiveBucketKey,
|
||||
easJsonBucketKey,
|
||||
packageJsonBucketKey,
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
},
|
||||
}));
|
||||
|
||||
Log.newLine();
|
||||
Log.succeed(
|
||||
`Workflow run started successfully. See logs: ${link(
|
||||
getWorkflowRunUrl(account.name, projectName, workflowRunId)
|
||||
)}`
|
||||
);
|
||||
Log.log(`See logs: ${link(getWorkflowRunUrl(account.name, projectName, workflowRunId))}`);
|
||||
} catch (err) {
|
||||
Log.error('Failed to start the workflow with the API.');
|
||||
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (!flags.wait) {
|
||||
Log.succeed('Workflow run started successfully.');
|
||||
|
||||
if (flags.json) {
|
||||
printJsonOnlyOutput({
|
||||
id: workflowRunId,
|
||||
url: getWorkflowRunUrl(account.name, projectName, workflowRunId),
|
||||
});
|
||||
}
|
||||
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
Log.newLine();
|
||||
const { status } = await waitForWorkflowRunToEndAsync(graphqlClient, {
|
||||
workflowRunId,
|
||||
});
|
||||
|
||||
if (flags.json) {
|
||||
const workflowRun = await WorkflowRunQuery.withJobsByIdAsync(graphqlClient, workflowRunId, {
|
||||
useCache: false,
|
||||
});
|
||||
|
||||
printJsonOnlyOutput({
|
||||
...workflowRun,
|
||||
url: getWorkflowRunUrl(account.name, projectName, workflowRunId),
|
||||
});
|
||||
}
|
||||
|
||||
if (status === WorkflowRunStatus.Failure) {
|
||||
process.exit(EXIT_CODES.WORKFLOW_FAILED);
|
||||
} else if (status === WorkflowRunStatus.Canceled) {
|
||||
process.exit(EXIT_CODES.WORKFLOW_CANCELED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function waitForWorkflowRunToEndAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
{ workflowRunId }: { workflowRunId: string }
|
||||
): Promise<WorkflowRunByIdQuery['workflowRuns']['byId']> {
|
||||
Log.log('Waiting for workflow run to complete. You can press Ctrl+C to exit.');
|
||||
|
||||
const spinner = ora('Currently waiting for workflow run to start.').start();
|
||||
|
||||
let failedFetchesCount = 0;
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
const workflowRun = await WorkflowRunQuery.byIdAsync(graphqlClient, workflowRunId, {
|
||||
useCache: false,
|
||||
});
|
||||
|
||||
failedFetchesCount = 0;
|
||||
|
||||
switch (workflowRun.status) {
|
||||
case WorkflowRunStatus.InProgress:
|
||||
spinner.start('Workflow run is in progress.');
|
||||
break;
|
||||
|
||||
case WorkflowRunStatus.ActionRequired:
|
||||
spinner.warn('Workflow run is waiting for action.');
|
||||
break;
|
||||
|
||||
case WorkflowRunStatus.PendingCancel:
|
||||
case WorkflowRunStatus.Canceled:
|
||||
spinner.warn('Workflow run has been canceled.');
|
||||
return workflowRun;
|
||||
|
||||
case WorkflowRunStatus.Failure:
|
||||
spinner.fail('Workflow run has failed.');
|
||||
return workflowRun;
|
||||
case WorkflowRunStatus.Success:
|
||||
spinner.succeed('Workflow run completed successfully.');
|
||||
return workflowRun;
|
||||
}
|
||||
} catch {
|
||||
spinner.text = '⚠ Failed to fetch the workflow run status. Check your network connection.';
|
||||
|
||||
failedFetchesCount += 1;
|
||||
|
||||
if (failedFetchesCount > 6) {
|
||||
spinner.fail('Failed to fetch the workflow run status 6 times in a row. Aborting wait.');
|
||||
process.exit(EXIT_CODES.WAIT_ABORTED);
|
||||
}
|
||||
}
|
||||
|
||||
await sleepAsync(10 /* seconds */ * 1000 /* milliseconds */);
|
||||
}
|
||||
}
|
||||
+176
-40
@@ -557,6 +557,8 @@ export type AccountMutation = {
|
||||
changePlan: Account;
|
||||
/** Add specified account Permissions for Actor. Actor must already have at least one permission on the account. */
|
||||
grantActorPermissions: Account;
|
||||
/** Remove profile image for the account. Do nothing if there's no profile image associated. */
|
||||
removeProfileImage: Account;
|
||||
/** Rename this account and the primary user's username if this account is a personal account */
|
||||
rename: Account;
|
||||
/** Requests a refund for the specified charge by requesting a manual refund from support */
|
||||
@@ -598,6 +600,11 @@ export type AccountMutationGrantActorPermissionsArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type AccountMutationRemoveProfileImageArgs = {
|
||||
accountID: Scalars['ID']['input'];
|
||||
};
|
||||
|
||||
|
||||
export type AccountMutationRenameArgs = {
|
||||
accountID: Scalars['ID']['input'];
|
||||
newName: Scalars['String']['input'];
|
||||
@@ -1395,6 +1402,7 @@ export type App = Project & {
|
||||
workerDeploymentsCrashes?: Maybe<WorkerDeploymentCrashes>;
|
||||
workerDeploymentsRequest: WorkerDeploymentRequestEdge;
|
||||
workerDeploymentsRequests?: Maybe<WorkerDeploymentRequests>;
|
||||
workflowRunGitBranchesPaginated: AppWorkflowRunGitBranchesConnection;
|
||||
workflowRunsPaginated: AppWorkflowRunsConnection;
|
||||
workflows: Array<Workflow>;
|
||||
};
|
||||
@@ -1681,10 +1689,21 @@ export type AppWorkerDeploymentsRequestsArgs = {
|
||||
};
|
||||
|
||||
|
||||
/** Represents an Exponent App (or Experience in legacy terms) */
|
||||
export type AppWorkflowRunGitBranchesPaginatedArgs = {
|
||||
after?: InputMaybe<Scalars['String']['input']>;
|
||||
before?: InputMaybe<Scalars['String']['input']>;
|
||||
filter?: InputMaybe<WorkflowRunGitBranchFilterInput>;
|
||||
first?: InputMaybe<Scalars['Int']['input']>;
|
||||
last?: InputMaybe<Scalars['Int']['input']>;
|
||||
};
|
||||
|
||||
|
||||
/** Represents an Exponent App (or Experience in legacy terms) */
|
||||
export type AppWorkflowRunsPaginatedArgs = {
|
||||
after?: InputMaybe<Scalars['String']['input']>;
|
||||
before?: InputMaybe<Scalars['String']['input']>;
|
||||
filter?: InputMaybe<WorkflowRunFilterInput>;
|
||||
first?: InputMaybe<Scalars['Int']['input']>;
|
||||
last?: InputMaybe<Scalars['Int']['input']>;
|
||||
};
|
||||
@@ -1821,10 +1840,10 @@ export type AppMutation = {
|
||||
__typename?: 'AppMutation';
|
||||
/** Create an app */
|
||||
createApp: App;
|
||||
/** Create an app and GitHub repository if user desire to */
|
||||
createAppAndGithubRepository: CreateAppAndGithubRepositoryResponse;
|
||||
/** @deprecated No longer supported */
|
||||
grantAccess?: Maybe<App>;
|
||||
/** Remove profile image (icon) for the app. Do nothing if there's no profile image associated. */
|
||||
removeProfileImage: App;
|
||||
/** Delete an App. Returns the ID of the background job receipt. Use BackgroundJobReceiptQuery to get the status of the job. */
|
||||
scheduleAppDeletion: BackgroundJobReceipt;
|
||||
/** Set display info for app */
|
||||
@@ -1841,17 +1860,17 @@ export type AppMutationCreateAppArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type AppMutationCreateAppAndGithubRepositoryArgs = {
|
||||
appInput: AppWithGithubRepositoryInput;
|
||||
};
|
||||
|
||||
|
||||
export type AppMutationGrantAccessArgs = {
|
||||
accessLevel?: InputMaybe<Scalars['String']['input']>;
|
||||
toUser: Scalars['ID']['input'];
|
||||
};
|
||||
|
||||
|
||||
export type AppMutationRemoveProfileImageArgs = {
|
||||
appId: Scalars['ID']['input'];
|
||||
};
|
||||
|
||||
|
||||
export type AppMutationScheduleAppDeletionArgs = {
|
||||
appId: Scalars['ID']['input'];
|
||||
};
|
||||
@@ -2188,6 +2207,24 @@ export type AppWorkflowRunEdge = {
|
||||
node: WorkflowRun;
|
||||
};
|
||||
|
||||
export type AppWorkflowRunGitBranchEdge = {
|
||||
__typename?: 'AppWorkflowRunGitBranchEdge';
|
||||
cursor: Scalars['String']['output'];
|
||||
node: AppWorkflowRunGitBranchNode;
|
||||
};
|
||||
|
||||
export type AppWorkflowRunGitBranchNode = {
|
||||
__typename?: 'AppWorkflowRunGitBranchNode';
|
||||
lastRunAt: Scalars['DateTime']['output'];
|
||||
name: Scalars['String']['output'];
|
||||
};
|
||||
|
||||
export type AppWorkflowRunGitBranchesConnection = {
|
||||
__typename?: 'AppWorkflowRunGitBranchesConnection';
|
||||
edges: Array<AppWorkflowRunGitBranchEdge>;
|
||||
pageInfo: PageInfo;
|
||||
};
|
||||
|
||||
export type AppWorkflowRunsConnection = {
|
||||
__typename?: 'AppWorkflowRunsConnection';
|
||||
edges: Array<AppWorkflowRunEdge>;
|
||||
@@ -2550,6 +2587,31 @@ export type AscApiKeyInput = {
|
||||
keyP8: Scalars['String']['input'];
|
||||
};
|
||||
|
||||
export type Asset = {
|
||||
__typename?: 'Asset';
|
||||
contentType: Scalars['String']['output'];
|
||||
fileSHA256: Scalars['String']['output'];
|
||||
fileSize: Scalars['Int']['output'];
|
||||
finalFileSize?: Maybe<Scalars['Int']['output']>;
|
||||
id: Scalars['ID']['output'];
|
||||
storageKey: Scalars['String']['output'];
|
||||
};
|
||||
|
||||
export type AssetMapGroup = {
|
||||
android?: InputMaybe<AssetMapSourceInput>;
|
||||
ios?: InputMaybe<AssetMapSourceInput>;
|
||||
web?: InputMaybe<AssetMapSourceInput>;
|
||||
};
|
||||
|
||||
export type AssetMapSourceInput = {
|
||||
bucketKey?: InputMaybe<Scalars['String']['input']>;
|
||||
type?: InputMaybe<AssetMapSourceType>;
|
||||
};
|
||||
|
||||
export enum AssetMapSourceType {
|
||||
Gcs = 'GCS'
|
||||
}
|
||||
|
||||
export type AssetMetadataResult = {
|
||||
__typename?: 'AssetMetadataResult';
|
||||
status: AssetMetadataStatus;
|
||||
@@ -2578,7 +2640,15 @@ export type AssetMutationGetSignedAssetUploadSpecificationsArgs = {
|
||||
/** Check to see if assets with given storageKeys exist */
|
||||
export type AssetQuery = {
|
||||
__typename?: 'AssetQuery';
|
||||
byStorageKeys: Array<Asset>;
|
||||
metadata: Array<AssetMetadataResult>;
|
||||
signedUrls: Array<AssetSignedUrlResult>;
|
||||
};
|
||||
|
||||
|
||||
/** Check to see if assets with given storageKeys exist */
|
||||
export type AssetQueryByStorageKeysArgs = {
|
||||
storageKeys: Array<Scalars['String']['input']>;
|
||||
};
|
||||
|
||||
|
||||
@@ -2587,6 +2657,20 @@ export type AssetQueryMetadataArgs = {
|
||||
storageKeys: Array<Scalars['String']['input']>;
|
||||
};
|
||||
|
||||
|
||||
/** Check to see if assets with given storageKeys exist */
|
||||
export type AssetQuerySignedUrlsArgs = {
|
||||
storageKeys: Array<Scalars['String']['input']>;
|
||||
updateId: Scalars['ID']['input'];
|
||||
};
|
||||
|
||||
export type AssetSignedUrlResult = {
|
||||
__typename?: 'AssetSignedUrlResult';
|
||||
headers?: Maybe<Scalars['JSON']['output']>;
|
||||
storageKey: Scalars['String']['output'];
|
||||
url: Scalars['String']['output'];
|
||||
};
|
||||
|
||||
export type AuditLog = {
|
||||
__typename?: 'AuditLog';
|
||||
account?: Maybe<Account>;
|
||||
@@ -2668,6 +2752,13 @@ export enum AuthProviderIdentifier {
|
||||
StubIdp = 'STUB_IDP'
|
||||
}
|
||||
|
||||
export type AverageAssetMetrics = {
|
||||
__typename?: 'AverageAssetMetrics';
|
||||
averageDownloadSizeBytes: Scalars['Int']['output'];
|
||||
count: Scalars['Int']['output'];
|
||||
storageKey: Scalars['String']['output'];
|
||||
};
|
||||
|
||||
export type BackgroundJobReceipt = {
|
||||
__typename?: 'BackgroundJobReceipt';
|
||||
account: Account;
|
||||
@@ -3417,12 +3508,6 @@ export type CreateAndroidSubmissionInput = {
|
||||
submittedBuildId?: InputMaybe<Scalars['ID']['input']>;
|
||||
};
|
||||
|
||||
export type CreateAppAndGithubRepositoryResponse = {
|
||||
__typename?: 'CreateAppAndGithubRepositoryResponse';
|
||||
app: App;
|
||||
cloneUrl?: Maybe<Scalars['String']['output']>;
|
||||
};
|
||||
|
||||
export type CreateBuildResult = {
|
||||
__typename?: 'CreateBuildResult';
|
||||
build: Build;
|
||||
@@ -3524,6 +3609,12 @@ export type CreateSubmissionResult = {
|
||||
submission: Submission;
|
||||
};
|
||||
|
||||
export type CumulativeAverageMetrics = {
|
||||
__typename?: 'CumulativeAverageMetrics';
|
||||
averageUpdatePayloadBytes: Scalars['Int']['output'];
|
||||
launchAssetCount: Scalars['Int']['output'];
|
||||
};
|
||||
|
||||
export type CumulativeMetrics = {
|
||||
__typename?: 'CumulativeMetrics';
|
||||
data: UpdatesMetricsData;
|
||||
@@ -3987,6 +4078,7 @@ export enum EasServiceMetric {
|
||||
AssetsRequests = 'ASSETS_REQUESTS',
|
||||
BandwidthUsage = 'BANDWIDTH_USAGE',
|
||||
Builds = 'BUILDS',
|
||||
LocalBuilds = 'LOCAL_BUILDS',
|
||||
ManifestRequests = 'MANIFEST_REQUESTS',
|
||||
RunTime = 'RUN_TIME',
|
||||
UniqueUpdaters = 'UNIQUE_UPDATERS',
|
||||
@@ -5818,7 +5910,6 @@ export enum ProjectArchiveSourceType {
|
||||
Gcs = 'GCS',
|
||||
Git = 'GIT',
|
||||
None = 'NONE',
|
||||
S3 = 'S3',
|
||||
Url = 'URL'
|
||||
}
|
||||
|
||||
@@ -5849,6 +5940,8 @@ export type PublicArtifacts = {
|
||||
};
|
||||
|
||||
export type PublishUpdateGroupInput = {
|
||||
assetHostOverride?: InputMaybe<Scalars['String']['input']>;
|
||||
assetMapGroup?: InputMaybe<AssetMapGroup>;
|
||||
awaitingCodeSigningInfo?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
branchId: Scalars['String']['input'];
|
||||
environment?: InputMaybe<EnvironmentVariableEnvironment>;
|
||||
@@ -5856,6 +5949,7 @@ export type PublishUpdateGroupInput = {
|
||||
fingerprintInfoGroup?: InputMaybe<FingerprintInfoGroup>;
|
||||
gitCommitHash?: InputMaybe<Scalars['String']['input']>;
|
||||
isGitWorkingTreeDirty?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
manifestHostOverride?: InputMaybe<Scalars['String']['input']>;
|
||||
message?: InputMaybe<Scalars['String']['input']>;
|
||||
rollBackToEmbeddedInfoGroup?: InputMaybe<UpdateRollBackToEmbeddedGroup>;
|
||||
rolloutInfoGroup?: InputMaybe<UpdateRolloutInfoGroup>;
|
||||
@@ -5877,6 +5971,7 @@ export enum RequestMethod {
|
||||
export type RequestsFilters = {
|
||||
cacheStatus?: InputMaybe<Array<ResponseCacheStatus>>;
|
||||
continent?: InputMaybe<Array<ContinentCode>>;
|
||||
country?: InputMaybe<Array<Scalars['String']['input']>>;
|
||||
hasCustomDomainOrigin?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
isAsset?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
isCrash?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
@@ -6283,6 +6378,7 @@ export type RootQueryAppByAppIdArgs = {
|
||||
|
||||
export type RootQueryUpdatesByGroupArgs = {
|
||||
group: Scalars['ID']['input'];
|
||||
platform?: InputMaybe<Scalars['String']['input']>;
|
||||
};
|
||||
|
||||
|
||||
@@ -6965,6 +7061,8 @@ export type Update = ActivityTimelineProjectActivity & {
|
||||
activityTimestamp: Scalars['DateTime']['output'];
|
||||
actor?: Maybe<Actor>;
|
||||
app: App;
|
||||
assetHostOverride?: Maybe<Scalars['String']['output']>;
|
||||
assetMapUrl?: Maybe<Scalars['String']['output']>;
|
||||
awaitingCodeSigningInfo: Scalars['Boolean']['output'];
|
||||
branch: UpdateBranch;
|
||||
branchId: Scalars['ID']['output'];
|
||||
@@ -6983,6 +7081,7 @@ export type Update = ActivityTimelineProjectActivity & {
|
||||
isRollBackToEmbedded: Scalars['Boolean']['output'];
|
||||
jobRun?: Maybe<JobRun>;
|
||||
manifestFragment: Scalars['String']['output'];
|
||||
manifestHostOverride?: Maybe<Scalars['String']['output']>;
|
||||
manifestPermalink: Scalars['String']['output'];
|
||||
message?: Maybe<Scalars['String']['output']>;
|
||||
platform: Scalars['String']['output'];
|
||||
@@ -7206,6 +7305,8 @@ export type UpdateInfoGroup = {
|
||||
|
||||
export type UpdateInsights = {
|
||||
__typename?: 'UpdateInsights';
|
||||
averageAssetMetrics: Array<AverageAssetMetrics>;
|
||||
cumulativeAverageMetrics: CumulativeAverageMetrics;
|
||||
cumulativeMetrics: CumulativeMetrics;
|
||||
id: Scalars['ID']['output'];
|
||||
totalUniqueUsers: Scalars['Int']['output'];
|
||||
@@ -7223,7 +7324,10 @@ export type UpdateInsightsTotalUniqueUsersArgs = {
|
||||
|
||||
export type UpdateMutation = {
|
||||
__typename?: 'UpdateMutation';
|
||||
/** Delete an EAS update group */
|
||||
/**
|
||||
* Delete an EAS update group
|
||||
* @deprecated Use scheduleUpdateGroupDeletion instead
|
||||
*/
|
||||
deleteUpdateGroup: DeleteUpdateGroupResult;
|
||||
/** Delete an EAS update group in the background */
|
||||
scheduleUpdateGroupDeletion: BackgroundJobReceipt;
|
||||
@@ -7333,6 +7437,7 @@ export enum UploadSessionType {
|
||||
/** @deprecated Use EAS_SUBMIT_GCS_APP_ARCHIVE instead. */
|
||||
EasSubmitAppArchive = 'EAS_SUBMIT_APP_ARCHIVE',
|
||||
EasSubmitGcsAppArchive = 'EAS_SUBMIT_GCS_APP_ARCHIVE',
|
||||
EasUpdateAssetsMetadata = 'EAS_UPDATE_ASSETS_METADATA',
|
||||
EasUpdateFingerprint = 'EAS_UPDATE_FINGERPRINT'
|
||||
}
|
||||
|
||||
@@ -7788,7 +7893,12 @@ export enum UserEntityTypeName {
|
||||
export type UserInvitation = {
|
||||
__typename?: 'UserInvitation';
|
||||
accountName: Scalars['String']['output'];
|
||||
/** If the invite is for a personal team, the profile photo of account owner */
|
||||
/** The profile image URL of the account owner */
|
||||
accountProfileImageUrl: Scalars['String']['output'];
|
||||
/**
|
||||
* If the invite is for a personal team, the profile photo of account owner
|
||||
* @deprecated Use accountProfileImageUrl
|
||||
*/
|
||||
accountProfilePhoto?: Maybe<Scalars['String']['output']>;
|
||||
created: Scalars['DateTime']['output'];
|
||||
/** Email to which this invitation was sent */
|
||||
@@ -7865,6 +7975,7 @@ export type UserInvitationMutationResendUserInvitationArgs = {
|
||||
export type UserInvitationPublicData = {
|
||||
__typename?: 'UserInvitationPublicData';
|
||||
accountName: Scalars['String']['output'];
|
||||
accountProfileImageUrl: Scalars['String']['output'];
|
||||
accountProfilePhoto?: Maybe<Scalars['String']['output']>;
|
||||
created: Scalars['DateTime']['output'];
|
||||
email: Scalars['String']['output'];
|
||||
@@ -8100,6 +8211,8 @@ export type WorkerDeployment = ActivityTimelineProjectActivity & {
|
||||
initiatingActor?: Maybe<Actor>;
|
||||
logs?: Maybe<WorkerDeploymentLogs>;
|
||||
requests?: Maybe<WorkerDeploymentRequests>;
|
||||
signedAssetsURL: Scalars['String']['output'];
|
||||
signedDeploymentURL: Scalars['String']['output'];
|
||||
subdomain: Scalars['String']['output'];
|
||||
url: Scalars['String']['output'];
|
||||
};
|
||||
@@ -8292,6 +8405,7 @@ export type WorkerDeploymentRequestNode = {
|
||||
requestId: Scalars['WorkerDeploymentRequestID']['output'];
|
||||
requestTimestamp: Scalars['DateTime']['output'];
|
||||
responseType: ResponseType;
|
||||
routerPath?: Maybe<Scalars['String']['output']>;
|
||||
scriptName: Scalars['String']['output'];
|
||||
search?: Maybe<Scalars['String']['output']>;
|
||||
status: Scalars['Int']['output'];
|
||||
@@ -8434,7 +8548,7 @@ export type WorkerDeploymentRequestsCacheStatusEdge = {
|
||||
|
||||
export type WorkerDeploymentRequestsContinentEdge = {
|
||||
__typename?: 'WorkerDeploymentRequestsContinentEdge';
|
||||
continent: ContinentCode;
|
||||
continent?: Maybe<ContinentCode>;
|
||||
node: WorkerDeploymentRequestsAggregationNode;
|
||||
};
|
||||
|
||||
@@ -8617,6 +8731,7 @@ export enum WorkflowJobType {
|
||||
GetBuild = 'GET_BUILD',
|
||||
MaestroTest = 'MAESTRO_TEST',
|
||||
RequireApproval = 'REQUIRE_APPROVAL',
|
||||
Slack = 'SLACK',
|
||||
Submission = 'SUBMISSION',
|
||||
Update = 'UPDATE'
|
||||
}
|
||||
@@ -8702,7 +8817,6 @@ export type WorkflowRun = ActivityTimelineProjectActivity & {
|
||||
gitCommitMessage?: Maybe<Scalars['String']['output']>;
|
||||
githubRepository?: Maybe<GitHubRepository>;
|
||||
id: Scalars['ID']['output'];
|
||||
initiatingUser?: Maybe<User>;
|
||||
jobs: Array<WorkflowJob>;
|
||||
name: Scalars['String']['output'];
|
||||
pullRequestNumber?: Maybe<Scalars['Int']['output']>;
|
||||
@@ -8731,6 +8845,14 @@ export type WorkflowRunError = {
|
||||
title?: Maybe<Scalars['String']['output']>;
|
||||
};
|
||||
|
||||
export type WorkflowRunFilterInput = {
|
||||
requestedGitRef?: InputMaybe<Scalars['String']['input']>;
|
||||
};
|
||||
|
||||
export type WorkflowRunGitBranchFilterInput = {
|
||||
searchTerm?: InputMaybe<Scalars['String']['input']>;
|
||||
};
|
||||
|
||||
export type WorkflowRunInput = {
|
||||
projectSource: WorkflowProjectSourceInput;
|
||||
};
|
||||
@@ -9465,6 +9587,16 @@ export type CreateKeystoreGenerationUrlMutationVariables = Exact<{ [key: string]
|
||||
|
||||
export type CreateKeystoreGenerationUrlMutation = { __typename?: 'RootMutation', keystoreGenerationUrl: { __typename?: 'KeystoreGenerationUrlMutation', createKeystoreGenerationUrl: { __typename?: 'KeystoreGenerationUrl', id: string, url: string } } };
|
||||
|
||||
export type CreateLocalBuildMutationVariables = Exact<{
|
||||
appId: Scalars['ID']['input'];
|
||||
jobInput: LocalBuildJobInput;
|
||||
artifactSource: LocalBuildArchiveSourceInput;
|
||||
metadata?: InputMaybe<BuildMetadataInput>;
|
||||
}>;
|
||||
|
||||
|
||||
export type CreateLocalBuildMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', createLocalBuild: { __typename?: 'CreateBuildResult', build: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, expirationDate?: any | null, isForIosSimulator: boolean, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string }, metrics?: { __typename?: 'BuildMetrics', buildWaitTime?: number | null, buildQueueTime?: number | null, buildDuration?: number | null } | null } } } };
|
||||
|
||||
export type GetSignedUploadMutationVariables = Exact<{
|
||||
contentTypes: Array<Scalars['String']['input']> | Scalars['String']['input'];
|
||||
}>;
|
||||
@@ -9477,7 +9609,7 @@ export type UpdatePublishMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type UpdatePublishMutation = { __typename?: 'RootMutation', updateBranch: { __typename?: 'UpdateBranchMutation', publishUpdateGroups: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }> } };
|
||||
export type UpdatePublishMutation = { __typename?: 'RootMutation', updateBranch: { __typename?: 'UpdateBranchMutation', publishUpdateGroups: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }> } };
|
||||
|
||||
export type SetCodeSigningInfoMutationVariables = Exact<{
|
||||
updateId: Scalars['ID']['input'];
|
||||
@@ -9493,17 +9625,7 @@ export type SetRolloutPercentageMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type SetRolloutPercentageMutation = { __typename?: 'RootMutation', update: { __typename?: 'UpdateMutation', setRolloutPercentage: { __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null } } };
|
||||
|
||||
export type CreateLocalBuildMutationVariables = Exact<{
|
||||
appId: Scalars['ID']['input'];
|
||||
jobInput: LocalBuildJobInput;
|
||||
artifactSource: LocalBuildArchiveSourceInput;
|
||||
metadata?: InputMaybe<BuildMetadataInput>;
|
||||
}>;
|
||||
|
||||
|
||||
export type CreateLocalBuildMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', createLocalBuild: { __typename?: 'CreateBuildResult', build: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, expirationDate?: any | null, isForIosSimulator: boolean, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string }, metrics?: { __typename?: 'BuildMetrics', buildWaitTime?: number | null, buildQueueTime?: number | null, buildDuration?: number | null } | null } } } };
|
||||
export type SetRolloutPercentageMutation = { __typename?: 'RootMutation', update: { __typename?: 'UpdateMutation', setRolloutPercentage: { __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null } } };
|
||||
|
||||
export type CreateAndroidSubmissionMutationVariables = Exact<{
|
||||
appId: Scalars['ID']['input'];
|
||||
@@ -9650,7 +9772,7 @@ export type BranchesByAppQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type BranchesByAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updates: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }> }> } } };
|
||||
export type BranchesByAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updates: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }> }> } } };
|
||||
|
||||
export type BranchesBasicPaginatedOnAppQueryVariables = Exact<{
|
||||
appId: Scalars['String']['input'];
|
||||
@@ -9671,7 +9793,7 @@ export type ViewBranchesOnUpdateChannelQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ViewBranchesOnUpdateChannelQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateChannelByName?: { __typename?: 'UpdateChannel', id: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> }> } | null } } };
|
||||
export type ViewBranchesOnUpdateChannelQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateChannelByName?: { __typename?: 'UpdateChannel', id: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> }> } | null } } };
|
||||
|
||||
export type BuildsByIdQueryVariables = Exact<{
|
||||
buildId: Scalars['ID']['input'];
|
||||
@@ -9719,7 +9841,7 @@ export type ViewUpdateChannelOnAppQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ViewUpdateChannelOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateChannelByName?: { __typename?: 'UpdateChannel', id: string, isPaused: boolean, name: string, updatedAt: any, createdAt: any, branchMapping: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> }> } | null } } };
|
||||
export type ViewUpdateChannelOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateChannelByName?: { __typename?: 'UpdateChannel', id: string, isPaused: boolean, name: string, updatedAt: any, createdAt: any, branchMapping: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> }> } | null } } };
|
||||
|
||||
export type ViewUpdateChannelsOnAppQueryVariables = Exact<{
|
||||
appId: Scalars['String']['input'];
|
||||
@@ -9728,7 +9850,7 @@ export type ViewUpdateChannelsOnAppQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ViewUpdateChannelsOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateChannels: Array<{ __typename?: 'UpdateChannel', id: string, isPaused: boolean, name: string, updatedAt: any, createdAt: any, branchMapping: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> }> }> } } };
|
||||
export type ViewUpdateChannelsOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateChannels: Array<{ __typename?: 'UpdateChannel', id: string, isPaused: boolean, name: string, updatedAt: any, createdAt: any, branchMapping: string, updateBranches: Array<{ __typename?: 'UpdateBranch', id: string, name: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> }> }> } } };
|
||||
|
||||
export type ViewUpdateChannelsPaginatedOnAppQueryVariables = Exact<{
|
||||
appId: Scalars['String']['input'];
|
||||
@@ -9864,7 +9986,7 @@ export type ViewUpdatesByGroupQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ViewUpdatesByGroupQuery = { __typename?: 'RootQuery', updatesByGroup: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }> };
|
||||
export type ViewUpdatesByGroupQuery = { __typename?: 'RootQuery', updatesByGroup: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }> };
|
||||
|
||||
export type ViewUpdateGroupsOnBranchQueryVariables = Exact<{
|
||||
appId: Scalars['String']['input'];
|
||||
@@ -9875,7 +9997,7 @@ export type ViewUpdateGroupsOnBranchQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ViewUpdateGroupsOnBranchQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateBranchByName?: { __typename?: 'UpdateBranch', id: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> } | null } } };
|
||||
export type ViewUpdateGroupsOnBranchQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateBranchByName?: { __typename?: 'UpdateBranch', id: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> } | null } } };
|
||||
|
||||
export type ViewUpdateGroupsOnAppQueryVariables = Exact<{
|
||||
appId: Scalars['String']['input'];
|
||||
@@ -9885,14 +10007,14 @@ export type ViewUpdateGroupsOnAppQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ViewUpdateGroupsOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> } } };
|
||||
export type ViewUpdateGroupsOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, updateGroups: Array<Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }>> } } };
|
||||
|
||||
export type UpdateByIdQueryVariables = Exact<{
|
||||
updateId: Scalars['ID']['input'];
|
||||
}>;
|
||||
|
||||
|
||||
export type UpdateByIdQuery = { __typename?: 'RootQuery', updates: { __typename?: 'UpdateQuery', byId: { __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null } } };
|
||||
export type UpdateByIdQuery = { __typename?: 'RootQuery', updates: { __typename?: 'UpdateQuery', byId: { __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null } } };
|
||||
|
||||
export type CurrentUserQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
@@ -9914,6 +10036,20 @@ export type WebhookByIdQueryVariables = Exact<{
|
||||
|
||||
export type WebhookByIdQuery = { __typename?: 'RootQuery', webhook: { __typename?: 'WebhookQuery', byId: { __typename?: 'Webhook', id: string, event: WebhookType, url: string, createdAt: any, updatedAt: any } } };
|
||||
|
||||
export type WorkflowRunByIdQueryVariables = Exact<{
|
||||
workflowRunId: Scalars['ID']['input'];
|
||||
}>;
|
||||
|
||||
|
||||
export type WorkflowRunByIdQuery = { __typename?: 'RootQuery', workflowRuns: { __typename?: 'WorkflowRunQuery', byId: { __typename?: 'WorkflowRun', id: string, status: WorkflowRunStatus } } };
|
||||
|
||||
export type WorkflowRunByIdWithJobsQueryVariables = Exact<{
|
||||
workflowRunId: Scalars['ID']['input'];
|
||||
}>;
|
||||
|
||||
|
||||
export type WorkflowRunByIdWithJobsQuery = { __typename?: 'RootQuery', workflowRuns: { __typename?: 'WorkflowRunQuery', byId: { __typename?: 'WorkflowRun', id: string, name: string, status: WorkflowRunStatus, createdAt: any, workflow: { __typename?: 'Workflow', id: string, name?: string | null, fileName: string }, jobs: Array<{ __typename?: 'WorkflowJob', id: string, key: string, name: string, type: WorkflowJobType, status: WorkflowJobStatus, outputs: any, createdAt: any }> } } };
|
||||
|
||||
export type AccountFragment = { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> };
|
||||
|
||||
export type AppFragment = { __typename?: 'App', id: string, name: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }, githubRepository?: { __typename?: 'GitHubRepository', id: string, metadata: { __typename?: 'GitHubRepositoryMetadata', githubRepoOwnerName: string, githubRepoName: string } } | null };
|
||||
@@ -9940,9 +10076,9 @@ export type StatuspageServiceFragment = { __typename?: 'StatuspageService', id:
|
||||
|
||||
export type SubmissionFragment = { __typename?: 'Submission', id: string, status: SubmissionStatus, platform: AppPlatform, logFiles: Array<string>, app: { __typename?: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, androidConfig?: { __typename?: 'AndroidSubmissionConfig', applicationIdentifier?: string | null, track: SubmissionAndroidTrack, releaseStatus?: SubmissionAndroidReleaseStatus | null, rollout?: number | null } | null, iosConfig?: { __typename?: 'IosSubmissionConfig', ascAppIdentifier: string, appleIdUsername?: string | null } | null, error?: { __typename?: 'SubmissionError', errorCode?: string | null, message?: string | null } | null };
|
||||
|
||||
export type UpdateFragment = { __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null };
|
||||
export type UpdateFragment = { __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null };
|
||||
|
||||
export type UpdateBranchFragment = { __typename?: 'UpdateBranch', id: string, name: string, updates: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }> };
|
||||
export type UpdateBranchFragment = { __typename?: 'UpdateBranch', id: string, name: string, updates: Array<{ __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, manifestHostOverride?: string | null, assetHostOverride?: string | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null }> };
|
||||
|
||||
export type UpdateBranchBasicInfoFragment = { __typename?: 'UpdateBranch', id: string, name: string };
|
||||
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
|
||||
import { withErrorHandlingAsync } from '../client';
|
||||
import {
|
||||
WorkflowRunByIdQuery,
|
||||
WorkflowRunByIdQueryVariables,
|
||||
WorkflowRunByIdWithJobsQuery,
|
||||
WorkflowRunByIdWithJobsQueryVariables,
|
||||
} from '../generated';
|
||||
|
||||
export const WorkflowRunQuery = {
|
||||
async byIdAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
workflowRunId: string,
|
||||
{ useCache = true }: { useCache?: boolean } = {}
|
||||
): Promise<WorkflowRunByIdQuery['workflowRuns']['byId']> {
|
||||
const data = await withErrorHandlingAsync(
|
||||
graphqlClient
|
||||
.query<WorkflowRunByIdQuery, WorkflowRunByIdQueryVariables>(
|
||||
gql`
|
||||
query WorkflowRunById($workflowRunId: ID!) {
|
||||
workflowRuns {
|
||||
byId(workflowRunId: $workflowRunId) {
|
||||
id
|
||||
status
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
{ workflowRunId },
|
||||
{
|
||||
requestPolicy: useCache ? 'cache-first' : 'network-only',
|
||||
additionalTypenames: ['WorkflowRun'],
|
||||
}
|
||||
)
|
||||
.toPromise()
|
||||
);
|
||||
return data.workflowRuns.byId;
|
||||
},
|
||||
async withJobsByIdAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
workflowRunId: string,
|
||||
{ useCache = true }: { useCache?: boolean } = {}
|
||||
): Promise<WorkflowRunByIdWithJobsQuery['workflowRuns']['byId']> {
|
||||
const data = await withErrorHandlingAsync(
|
||||
graphqlClient
|
||||
.query<WorkflowRunByIdWithJobsQuery, WorkflowRunByIdWithJobsQueryVariables>(
|
||||
gql`
|
||||
query WorkflowRunByIdWithJobs($workflowRunId: ID!) {
|
||||
workflowRuns {
|
||||
byId(workflowRunId: $workflowRunId) {
|
||||
id
|
||||
name
|
||||
status
|
||||
createdAt
|
||||
|
||||
workflow {
|
||||
id
|
||||
name
|
||||
fileName
|
||||
}
|
||||
|
||||
jobs {
|
||||
id
|
||||
key
|
||||
name
|
||||
type
|
||||
status
|
||||
outputs
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
{ workflowRunId },
|
||||
{
|
||||
requestPolicy: useCache ? 'cache-first' : 'network-only',
|
||||
additionalTypenames: ['WorkflowRun'],
|
||||
}
|
||||
)
|
||||
.toPromise()
|
||||
);
|
||||
return data.workflowRuns.byId;
|
||||
},
|
||||
};
|
||||
@@ -45,5 +45,7 @@ export const UpdateFragmentNode = gql`
|
||||
isDebugFingerprint
|
||||
}
|
||||
}
|
||||
manifestHostOverride
|
||||
assetHostOverride
|
||||
}
|
||||
`;
|
||||
@@ -424,7 +424,7 @@ describe(collectAssetsAsync, () => {
|
||||
expect(await collectAssetsAsync(inputDir)).toEqual({
|
||||
android: {
|
||||
launchAsset: {
|
||||
fileExtension: '.bundle',
|
||||
fileExtension: '.js',
|
||||
contentType: 'application/javascript',
|
||||
path: `${inputDir}/bundles/android.js`,
|
||||
},
|
||||
@@ -432,7 +432,7 @@ describe(collectAssetsAsync, () => {
|
||||
},
|
||||
ios: {
|
||||
launchAsset: {
|
||||
fileExtension: '.bundle',
|
||||
fileExtension: '.js',
|
||||
contentType: 'application/javascript',
|
||||
path: `${inputDir}/bundles/ios.js`,
|
||||
},
|
||||
@@ -440,7 +440,7 @@ describe(collectAssetsAsync, () => {
|
||||
},
|
||||
web: {
|
||||
launchAsset: {
|
||||
fileExtension: '.bundle',
|
||||
fileExtension: '.js',
|
||||
contentType: 'application/javascript',
|
||||
path: `${inputDir}/bundles/web.js`,
|
||||
},
|
||||
|
||||
@@ -69,7 +69,7 @@ describe(resolveGradleBuildContextAsync, () => {
|
||||
} as any,
|
||||
vcsClient
|
||||
);
|
||||
expect(gradleContext).toEqual({ moduleName: 'app', flavor: 'abc' });
|
||||
expect(gradleContext).toEqual({ moduleName: 'app', flavor: 'abc', buildType: 'release' });
|
||||
});
|
||||
|
||||
it('returns undefined if build.gradle does not exist', async () => {
|
||||
|
||||
@@ -144,6 +144,12 @@ describe(parseGradleCommand, () => {
|
||||
});
|
||||
expect(result).toEqual({ moduleName: 'app', flavor: 'example', buildType: 'release' });
|
||||
});
|
||||
test('parsing :app:buildExampleStage', async () => {
|
||||
const result = parseGradleCommand(':app:buildExampleStage', {
|
||||
android: { productFlavors: { example: {} } },
|
||||
});
|
||||
expect(result).toEqual({ moduleName: 'app', flavor: 'example', buildType: 'stage' });
|
||||
});
|
||||
test('parsing :app:buildExampleDebug when flavor is named with uper-case', async () => {
|
||||
const result = parseGradleCommand(':app:buildExampleRelease', {
|
||||
android: { productFlavors: { Example: {} } },
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Client } from '../../vcs/vcs';
|
||||
export interface GradleBuildContext {
|
||||
moduleName?: string;
|
||||
flavor?: string;
|
||||
buildType?: string;
|
||||
}
|
||||
|
||||
export async function resolveGradleBuildContextAsync(
|
||||
@@ -32,9 +33,11 @@ export async function resolveGradleBuildContextAsync(
|
||||
`Building modules different than "${gradleUtils.DEFAULT_MODULE_NAME}" might result in unexpected behavior.`
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
moduleName: parsedGradleCommand?.moduleName ?? gradleUtils.DEFAULT_MODULE_NAME,
|
||||
flavor: parsedGradleCommand?.flavor,
|
||||
buildType: parsedGradleCommand?.buildType,
|
||||
};
|
||||
} else {
|
||||
return { moduleName: gradleUtils.DEFAULT_MODULE_NAME };
|
||||
|
||||
@@ -82,7 +82,7 @@ export function parseGradleCommand(cmd: string, buildGradle: AppBuildGradle): Gr
|
||||
const [moduleName, taskName] =
|
||||
splitCmd.length > 1 ? [splitCmd[0], splitCmd[1]] : [undefined, splitCmd[0]];
|
||||
|
||||
const matchResult = taskName.match(/(build|bundle|assemble|package)(.*)(Release|Debug)/);
|
||||
const matchResult = taskName.match(/(build|bundle|assemble|package)(.*)([A-Z][a-z]+)/);
|
||||
if (!matchResult) {
|
||||
throw new Error(`Failed to parse gradle command: ${cmd}`);
|
||||
}
|
||||
@@ -104,9 +104,14 @@ export function parseGradleCommand(cmd: string, buildGradle: AppBuildGradle): Gr
|
||||
throw new Error(`flavor ${firstLetter.toLowerCase().concat(rest)} is not defined`);
|
||||
}
|
||||
}
|
||||
|
||||
const buildType = matchResult[3]
|
||||
? matchResult[3].charAt(0).toLowerCase() + matchResult[3].slice(1)
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
moduleName,
|
||||
flavor,
|
||||
buildType: matchResult[3] ? matchResult[3].toLowerCase() : undefined,
|
||||
buildType,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import chalk from 'chalk';
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
|
||||
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
|
||||
import { AssetMapSourceInput, AssetMapSourceType, UploadSessionType } from '../graphql/generated';
|
||||
import Log from '../log';
|
||||
import { uploadFileAtPathToGCSAsync } from '../uploads';
|
||||
import { formatBytes } from '../utils/files';
|
||||
import { createProgressTracker } from '../utils/progress';
|
||||
|
||||
export async function maybeUploadAssetMapAsync(
|
||||
distRoot: string,
|
||||
graphqlClient: ExpoGraphqlClient
|
||||
): Promise<AssetMapSourceInput | null> {
|
||||
const assetMapPath = path.join(distRoot, 'assetmap.json');
|
||||
|
||||
if (!(await fs.pathExists(assetMapPath))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let gcsBucketKey = undefined;
|
||||
const fileStat = await fs.promises.stat(assetMapPath);
|
||||
try {
|
||||
gcsBucketKey = await uploadFileAtPathToGCSAsync(
|
||||
graphqlClient,
|
||||
UploadSessionType.EasUpdateAssetsMetadata,
|
||||
assetMapPath,
|
||||
createProgressTracker({
|
||||
total: fileStat.size,
|
||||
message: ratio =>
|
||||
`Uploading assetmap.json (${formatBytes(fileStat.size * ratio)} / ${formatBytes(
|
||||
fileStat.size
|
||||
)})`,
|
||||
completedMessage: (duration: string) => `Uploaded assetmap.json ${chalk.dim(duration)}`,
|
||||
})
|
||||
);
|
||||
} catch (err: any) {
|
||||
let errMessage = 'Failed to upload assetmap to EAS';
|
||||
|
||||
if (err.message) {
|
||||
errMessage += `\n\nReason: ${err.message}`;
|
||||
}
|
||||
|
||||
Log.warn(errMessage);
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
type: AssetMapSourceType.Gcs,
|
||||
bucketKey: gcsBucketKey,
|
||||
};
|
||||
}
|
||||
@@ -16,10 +16,18 @@ export async function validateMetroConfigForManagedWorkflowAsync(
|
||||
}
|
||||
|
||||
const metroConfig = await loadConfigAsync(ctx.projectDir);
|
||||
|
||||
// SDK <50 | plugins whose presence can be used to determine if the config is extending Expo's Metro config
|
||||
const hasHashAssetFilesPlugin = metroConfig.transformer?.assetPlugins?.find((plugin: string) =>
|
||||
plugin.match(/expo-asset[/|\\]tools[/|\\]hashAssetFiles/)
|
||||
);
|
||||
if (!hasHashAssetFilesPlugin) {
|
||||
|
||||
// SDK >=51 | this is a custom property that we inject to ensure cache invalidation between projects.
|
||||
const isExtendingExpoMetroConfig = metroConfig.transformer.hasOwnProperty(
|
||||
'_expoRelativeProjectRoot'
|
||||
);
|
||||
|
||||
if (!isExtendingExpoMetroConfig && !hasHashAssetFilesPlugin) {
|
||||
Log.warn(
|
||||
`It looks like that you are using a custom ${chalk.bold(
|
||||
'metro.config.js'
|
||||
|
||||
@@ -13,19 +13,13 @@ import Log, { learnMore } from '../log';
|
||||
import { Actor } from '../user/User';
|
||||
import { expoCommandAsync } from '../utils/expoCli';
|
||||
|
||||
export function getUsername(exp: ExpoConfig, user: Actor): string | undefined {
|
||||
export function getUsernameForBuildMetadataAndBuildJob(user: Actor): string | undefined {
|
||||
switch (user.__typename) {
|
||||
case 'User':
|
||||
return user.username;
|
||||
case 'SSOUser':
|
||||
return user.username;
|
||||
case 'Robot':
|
||||
// owner field is necessary to run `expo prebuild`
|
||||
if (!exp.owner) {
|
||||
throw new Error(
|
||||
'The "owner" manifest property is required when using robot users. See: https://docs.expo.dev/versions/latest/config/app/#owner'
|
||||
);
|
||||
}
|
||||
// robot users don't have usernames
|
||||
return undefined;
|
||||
}
|
||||
@@ -84,8 +78,12 @@ export function isExpoUpdatesInstalledOrAvailable(
|
||||
return isExpoUpdatesInstalled(projectDir);
|
||||
}
|
||||
|
||||
export function isUsingEASUpdate(exp: ExpoConfig, projectId: string): boolean {
|
||||
return exp.updates?.url === getEASUpdateURL(projectId);
|
||||
export function isUsingEASUpdate(
|
||||
exp: ExpoConfig,
|
||||
projectId: string,
|
||||
manifestHostOverride: string | null
|
||||
): boolean {
|
||||
return exp.updates?.url === getEASUpdateURL(projectId, manifestHostOverride);
|
||||
}
|
||||
|
||||
export async function getExpoUpdatesPackageVersionIfInstalledAsync(
|
||||
|
||||
@@ -94,7 +94,7 @@ type UpdateInfoGroup = {
|
||||
};
|
||||
|
||||
// Partial copy of `@expo/dev-server` `BundleAssetWithFileHashes`
|
||||
type AssetMap = Record<
|
||||
export type AssetMap = Record<
|
||||
string,
|
||||
{
|
||||
httpServerLocation: string;
|
||||
@@ -374,7 +374,7 @@ export function filterCollectedAssetsByRequestedPlatforms(
|
||||
}
|
||||
|
||||
/** Try to load the asset map for logging the names of assets published */
|
||||
export async function loadAssetMapAsync(distRoot: string): Promise<AssetMap | null> {
|
||||
async function loadAssetMapAsync(distRoot: string): Promise<AssetMap | null> {
|
||||
const assetMapPath = path.join(distRoot, 'assetmap.json');
|
||||
|
||||
if (!(await fs.pathExists(assetMapPath))) {
|
||||
@@ -421,7 +421,8 @@ export async function collectAssetsAsync(dir: string): Promise<CollectedAssets>
|
||||
for (const platform of Object.keys(metadata.fileMetadata) as ExpoConfigPlatform[]) {
|
||||
collectedAssets[platform] = {
|
||||
launchAsset: {
|
||||
fileExtension: '.bundle',
|
||||
// path.extname() returns an empty string when there's no extension so we use || to fall back to .bundle
|
||||
fileExtension: path.extname(metadata.fileMetadata[platform].bundle) || '.bundle',
|
||||
contentType: 'application/javascript',
|
||||
path: path.resolve(dir, metadata.fileMetadata[platform].bundle),
|
||||
},
|
||||
@@ -1072,27 +1073,52 @@ export async function getRuntimeToUpdateRolloutInfoGroupMappingAsync(
|
||||
runtimeToPlatformsAndFingerprintInfoMapping.map(r => [r.runtimeVersion, r.platforms])
|
||||
);
|
||||
return await mapMapAsync(runtimeToPlatformsMap, async (platforms, runtimeVersion) => {
|
||||
return Object.fromEntries(
|
||||
await Promise.all(
|
||||
platforms.map<Promise<[string, UpdateRolloutInfo]>>(async platform => {
|
||||
const updateIdForPlatform = await BranchQuery.getLatestUpdateIdOnBranchAsync(
|
||||
graphqlClient,
|
||||
{
|
||||
appId,
|
||||
branchName,
|
||||
runtimeVersion,
|
||||
platform: updatePublishPlatformToAppPlatform[platform],
|
||||
}
|
||||
);
|
||||
if (!updateIdForPlatform) {
|
||||
throw new Error(
|
||||
`No updates on branch ${branchName} for platform ${platform} and runtimeVersion ${runtimeVersion} to roll out from.`
|
||||
);
|
||||
}
|
||||
|
||||
return [platform, { rolloutPercentage, rolloutControlUpdateId: updateIdForPlatform }];
|
||||
})
|
||||
)
|
||||
);
|
||||
return await getUpdateRolloutInfoGroupAsync(graphqlClient, {
|
||||
appId,
|
||||
branchName,
|
||||
rolloutPercentage,
|
||||
runtimeVersion,
|
||||
platforms,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function getUpdateRolloutInfoGroupAsync(
|
||||
graphqlClient: ExpoGraphqlClient,
|
||||
{
|
||||
appId,
|
||||
branchName,
|
||||
rolloutPercentage,
|
||||
runtimeVersion,
|
||||
platforms,
|
||||
}: {
|
||||
appId: string;
|
||||
branchName: string;
|
||||
rolloutPercentage: number;
|
||||
runtimeVersion: string;
|
||||
platforms: UpdatePublishPlatform[];
|
||||
}
|
||||
): Promise<UpdateRolloutInfoGroup> {
|
||||
return Object.fromEntries(
|
||||
await Promise.all(
|
||||
platforms.map<Promise<[string, UpdateRolloutInfo]>>(async platform => {
|
||||
const updateIdForPlatform = await BranchQuery.getLatestUpdateIdOnBranchAsync(
|
||||
graphqlClient,
|
||||
{
|
||||
appId,
|
||||
branchName,
|
||||
runtimeVersion,
|
||||
platform: updatePublishPlatformToAppPlatform[platform],
|
||||
}
|
||||
);
|
||||
if (!updateIdForPlatform) {
|
||||
throw new Error(
|
||||
`No updates on branch ${branchName} for platform ${platform} and runtimeVersion ${runtimeVersion} to roll out from.`
|
||||
);
|
||||
}
|
||||
|
||||
return [platform, { rolloutPercentage, rolloutControlUpdateId: updateIdForPlatform }];
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -98,17 +98,19 @@ async function ensureEASUpdatesIsConfiguredInExpoConfigAsync({
|
||||
projectDir,
|
||||
platform,
|
||||
workflows,
|
||||
manifestHostOverride,
|
||||
}: {
|
||||
exp: ExpoConfig;
|
||||
projectId: string;
|
||||
projectDir: string;
|
||||
platform: RequestedPlatform;
|
||||
workflows: Record<Platform, Workflow>;
|
||||
manifestHostOverride: string | null;
|
||||
}): Promise<{ projectChanged: boolean; exp: ExpoConfig }> {
|
||||
const modifyConfig: Partial<ExpoConfig> = {};
|
||||
|
||||
if (exp.updates?.url !== getEASUpdateURL(projectId)) {
|
||||
modifyConfig.updates = { url: getEASUpdateURL(projectId) };
|
||||
if (exp.updates?.url !== getEASUpdateURL(projectId, manifestHostOverride)) {
|
||||
modifyConfig.updates = { url: getEASUpdateURL(projectId, manifestHostOverride) };
|
||||
}
|
||||
|
||||
let androidRuntimeVersion = exp.android?.runtimeVersion ?? exp.runtimeVersion;
|
||||
@@ -372,6 +374,7 @@ export async function ensureEASUpdateIsConfiguredAsync({
|
||||
platform,
|
||||
env,
|
||||
forceNativeConfigSync,
|
||||
manifestHostOverride,
|
||||
}: {
|
||||
exp: ExpoConfig;
|
||||
projectId: string;
|
||||
@@ -380,6 +383,7 @@ export async function ensureEASUpdateIsConfiguredAsync({
|
||||
platform: RequestedPlatform | null;
|
||||
env: Env | undefined;
|
||||
forceNativeConfigSync?: boolean;
|
||||
manifestHostOverride: string | null;
|
||||
}): Promise<void> {
|
||||
const hasExpoUpdates = isExpoUpdatesInstalledOrAvailable(
|
||||
projectDir,
|
||||
@@ -409,6 +413,7 @@ export async function ensureEASUpdateIsConfiguredAsync({
|
||||
projectId,
|
||||
platform,
|
||||
workflows,
|
||||
manifestHostOverride,
|
||||
});
|
||||
|
||||
if (forceNativeConfigSync || projectChanged || !hasExpoUpdates) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import { PublishMutation } from '../graphql/mutations/PublishMutation';
|
||||
import Log, { link } from '../log';
|
||||
import { ora } from '../ora';
|
||||
import { getOwnerAccountForProjectIdAsync } from '../project/projectUtils';
|
||||
import { UpdatePublishPlatform, getUpdateRolloutInfoGroupAsync } from '../project/publish';
|
||||
import {
|
||||
CodeSigningInfo,
|
||||
checkDirectiveBodyAgainstUpdateInfoGroup,
|
||||
@@ -39,6 +40,7 @@ export async function republishAsync({
|
||||
updateMessage,
|
||||
codeSigningInfo,
|
||||
json,
|
||||
rolloutPercentage,
|
||||
}: {
|
||||
graphqlClient: ExpoGraphqlClient;
|
||||
app: { exp: ExpoConfig; projectId: string };
|
||||
@@ -47,6 +49,7 @@ export async function republishAsync({
|
||||
updateMessage: string;
|
||||
codeSigningInfo?: CodeSigningInfo;
|
||||
json?: boolean;
|
||||
rolloutPercentage?: number;
|
||||
}): Promise<void> {
|
||||
const { branchName: targetBranchName, branchId: targetBranchId } = targetBranch;
|
||||
|
||||
@@ -57,7 +60,9 @@ export async function republishAsync({
|
||||
update.groupId === arbitraryUpdate.groupId &&
|
||||
update.branchId === arbitraryUpdate.branchId &&
|
||||
update.branchName === arbitraryUpdate.branchName &&
|
||||
update.runtimeVersion === arbitraryUpdate.runtimeVersion;
|
||||
update.runtimeVersion === arbitraryUpdate.runtimeVersion &&
|
||||
update.manifestHostOverride === arbitraryUpdate.manifestHostOverride &&
|
||||
update.assetHostOverride === arbitraryUpdate.assetHostOverride;
|
||||
assert(
|
||||
updatesToPublish.every(isSameGroup),
|
||||
'All updates being republished must belong to the same update group'
|
||||
@@ -139,6 +144,15 @@ export async function republishAsync({
|
||||
];
|
||||
})
|
||||
),
|
||||
rolloutInfoGroup: rolloutPercentage
|
||||
? await getUpdateRolloutInfoGroupAsync(graphqlClient, {
|
||||
appId: app.projectId,
|
||||
branchName: targetBranchName,
|
||||
runtimeVersion,
|
||||
rolloutPercentage,
|
||||
platforms: updatesToPublish.map(update => update.platform as UpdatePublishPlatform),
|
||||
})
|
||||
: null,
|
||||
};
|
||||
|
||||
updatesRepublished = await PublishMutation.publishUpdateGroupAsync(graphqlClient, [
|
||||
@@ -149,6 +163,8 @@ export async function republishAsync({
|
||||
...objectToMergeIn,
|
||||
gitCommitHash: updatesToPublish[0].gitCommitHash,
|
||||
awaitingCodeSigningInfo: !!codeSigningInfo,
|
||||
manifestHostOverride: updatesToPublish[0].manifestHostOverride,
|
||||
assetHostOverride: updatesToPublish[0].assetHostOverride,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -226,6 +242,22 @@ export async function republishAsync({
|
||||
...(updatesRepublishedByPlatform.ios
|
||||
? [{ label: 'iOS update ID', value: updatesRepublishedByPlatform.ios.id }]
|
||||
: []),
|
||||
...(updatesRepublishedByPlatform.android?.rolloutControlUpdate
|
||||
? [
|
||||
{
|
||||
label: 'Android Rollout',
|
||||
value: `${updatesRepublishedByPlatform.android?.rolloutPercentage}% (Base update ID: ${updatesRepublishedByPlatform.android?.rolloutControlUpdate.id})`,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(updatesRepublishedByPlatform.ios?.rolloutControlUpdate
|
||||
? [
|
||||
{
|
||||
label: 'iOS Rollout',
|
||||
value: `${updatesRepublishedByPlatform.ios?.rolloutPercentage}% (Base update ID: ${updatesRepublishedByPlatform.ios?.rolloutControlUpdate.id})`,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{ label: 'Message', value: updateMessage },
|
||||
{ label: 'EAS Dashboard', value: link(updateGroupUrl, { dim: false }) },
|
||||
])
|
||||
|
||||
@@ -3,7 +3,6 @@ import { format } from '@expo/timeago.js';
|
||||
import chalk from 'chalk';
|
||||
import dateFormat from 'dateformat';
|
||||
|
||||
import { getEASUpdateURL } from '../api';
|
||||
import {
|
||||
Robot,
|
||||
SsoUser,
|
||||
@@ -270,13 +269,3 @@ export function getBranchDescription(branch: UpdateBranchFragment): FormattedBra
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export async function checkEASUpdateURLIsSetAsync(
|
||||
exp: ExpoConfig,
|
||||
projectId: string
|
||||
): Promise<boolean> {
|
||||
const configuredURL = exp.updates?.url;
|
||||
const expectedURL = getEASUpdateURL(projectId);
|
||||
|
||||
return configuredURL === expectedURL;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { IOSConfig } from '@expo/config-plugins';
|
||||
import plist from '@expo/plist';
|
||||
import binaryPlist from 'bplist-parser';
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
|
||||
@@ -25,3 +26,24 @@ export async function writePlistAsync(
|
||||
await fs.mkdirp(path.dirname(plistPath));
|
||||
await fs.writeFile(plistPath, contents);
|
||||
}
|
||||
|
||||
const CHAR_CHEVRON_OPEN = 60;
|
||||
const CHAR_B_LOWER = 98;
|
||||
|
||||
export function parseBinaryPlistBuffer(contents: Buffer): any {
|
||||
if (contents[0] === CHAR_CHEVRON_OPEN) {
|
||||
const info = plist.parse(contents.toString());
|
||||
if (Array.isArray(info)) {
|
||||
return info[0];
|
||||
}
|
||||
return info;
|
||||
} else if (contents[0] === CHAR_B_LOWER) {
|
||||
const info = binaryPlist.parseBuffer(contents);
|
||||
if (Array.isArray(info)) {
|
||||
return info[0];
|
||||
}
|
||||
return info;
|
||||
} else {
|
||||
throw new Error(`Cannot parse plist of type byte (0x${contents[0].toString(16)})`);
|
||||
}
|
||||
}
|
||||
@@ -104,7 +104,7 @@ export default class GitClient extends Client {
|
||||
commitAllFiles?: boolean;
|
||||
nonInteractive: boolean;
|
||||
}): Promise<void> {
|
||||
await ensureGitConfiguredAsync({ nonInteractive });
|
||||
await this.ensureGitConfiguredAsync({ nonInteractive });
|
||||
|
||||
try {
|
||||
if (commitAllFiles) {
|
||||
@@ -391,74 +391,84 @@ export default class GitClient extends Client {
|
||||
public override canGetLastCommitMessage(): boolean {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
async function ensureGitConfiguredAsync({
|
||||
nonInteractive,
|
||||
}: {
|
||||
nonInteractive: boolean;
|
||||
}): Promise<void> {
|
||||
let usernameConfigured = true;
|
||||
let emailConfigured = true;
|
||||
try {
|
||||
await spawnAsync('git', ['config', '--get', 'user.name']);
|
||||
} catch (err: any) {
|
||||
Log.debug(err);
|
||||
usernameConfigured = false;
|
||||
}
|
||||
try {
|
||||
await spawnAsync('git', ['config', '--get', 'user.email']);
|
||||
} catch (err: any) {
|
||||
Log.debug(err);
|
||||
emailConfigured = false;
|
||||
}
|
||||
if (usernameConfigured && emailConfigured) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log.warn(
|
||||
`You need to configure Git with your ${[
|
||||
!usernameConfigured && 'username (user.name)',
|
||||
!emailConfigured && 'email address (user.email)',
|
||||
]
|
||||
.filter(i => i)
|
||||
.join(' and ')}`
|
||||
);
|
||||
if (nonInteractive) {
|
||||
throw new Error('Git cannot be configured automatically in non-interactive mode');
|
||||
}
|
||||
if (!usernameConfigured) {
|
||||
const { username } = await promptAsync({
|
||||
type: 'text',
|
||||
name: 'username',
|
||||
message: 'Username:',
|
||||
validate: (input: string) => input !== '',
|
||||
});
|
||||
const spinner = ora(
|
||||
`Running ${chalk.bold(`git config --local user.name ${username}`)}`
|
||||
).start();
|
||||
private async ensureGitConfiguredAsync({
|
||||
nonInteractive,
|
||||
}: {
|
||||
nonInteractive: boolean;
|
||||
}): Promise<void> {
|
||||
let usernameConfigured = true;
|
||||
let emailConfigured = true;
|
||||
try {
|
||||
await spawnAsync('git', ['config', '--local', 'user.name', username]);
|
||||
spinner.succeed();
|
||||
await spawnAsync('git', ['config', '--get', 'user.name'], {
|
||||
cwd: this.maybeCwdOverride,
|
||||
});
|
||||
} catch (err: any) {
|
||||
spinner.fail();
|
||||
throw err;
|
||||
Log.debug(err);
|
||||
usernameConfigured = false;
|
||||
}
|
||||
}
|
||||
if (!emailConfigured) {
|
||||
const { email } = await promptAsync({
|
||||
type: 'text',
|
||||
name: 'email',
|
||||
message: 'Email address:',
|
||||
validate: (input: string) => input !== '',
|
||||
});
|
||||
const spinner = ora(`Running ${chalk.bold(`git config --local user.email ${email}`)}`).start();
|
||||
try {
|
||||
await spawnAsync('git', ['config', '--local', 'user.email', email]);
|
||||
spinner.succeed();
|
||||
await spawnAsync('git', ['config', '--get', 'user.email'], {
|
||||
cwd: this.maybeCwdOverride,
|
||||
});
|
||||
} catch (err: any) {
|
||||
spinner.fail();
|
||||
throw err;
|
||||
Log.debug(err);
|
||||
emailConfigured = false;
|
||||
}
|
||||
if (usernameConfigured && emailConfigured) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log.warn(
|
||||
`You need to configure Git with your ${[
|
||||
!usernameConfigured && 'username (user.name)',
|
||||
!emailConfigured && 'email address (user.email)',
|
||||
]
|
||||
.filter(i => i)
|
||||
.join(' and ')}`
|
||||
);
|
||||
if (nonInteractive) {
|
||||
throw new Error('Git cannot be configured automatically in non-interactive mode');
|
||||
}
|
||||
if (!usernameConfigured) {
|
||||
const { username } = await promptAsync({
|
||||
type: 'text',
|
||||
name: 'username',
|
||||
message: 'Username:',
|
||||
validate: (input: string) => input !== '',
|
||||
});
|
||||
const spinner = ora(
|
||||
`Running ${chalk.bold(`git config --local user.name ${username}`)}`
|
||||
).start();
|
||||
try {
|
||||
await spawnAsync('git', ['config', '--local', 'user.name', username], {
|
||||
cwd: this.maybeCwdOverride,
|
||||
});
|
||||
spinner.succeed();
|
||||
} catch (err: any) {
|
||||
spinner.fail();
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
if (!emailConfigured) {
|
||||
const { email } = await promptAsync({
|
||||
type: 'text',
|
||||
name: 'email',
|
||||
message: 'Email address:',
|
||||
validate: (input: string) => input !== '',
|
||||
});
|
||||
const spinner = ora(
|
||||
`Running ${chalk.bold(`git config --local user.email ${email}`)}`
|
||||
).start();
|
||||
try {
|
||||
await spawnAsync('git', ['config', '--local', 'user.email', email], {
|
||||
cwd: this.maybeCwdOverride,
|
||||
});
|
||||
spinner.succeed();
|
||||
} catch (err: any) {
|
||||
spinner.fail();
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,8 +130,22 @@ export async function uploadAsync(params: UploadParams): Promise<UploadResult> {
|
||||
}
|
||||
|
||||
const getErrorMessageAsync = async (): Promise<string> => {
|
||||
const body = await response.json().catch(() => null);
|
||||
return body?.error ?? `Upload of "${filePath}" failed: ${response.statusText}`;
|
||||
const rayId = response.headers.get('cf-ray');
|
||||
const contentType = response.headers.get('Content-Type');
|
||||
if (contentType?.startsWith('text/html')) {
|
||||
// NOTE(@kitten): We've received a CDN error most likely. There's not much we can do
|
||||
// except for quoting the Request ID, so a user can send it to us. We can check
|
||||
// why a request was blocked by looking up a WAF event via the "Ray ID" here:
|
||||
// https://dash.cloudflare.com/e6f39f67f543faa6038768e8f37e4234/expo.app/security/events
|
||||
let message = `CDN firewall has aborted the upload with ${response.statusText}.`;
|
||||
if (rayId) {
|
||||
message += `\nReport this error quoting Request ID ${rayId}`;
|
||||
}
|
||||
return `Upload of "${filePath}" failed: ${message}`;
|
||||
} else {
|
||||
const json = await response.json().catch(() => null);
|
||||
return json?.error ?? `Upload of "${filePath}" failed: ${response.statusText}`;
|
||||
}
|
||||
};
|
||||
|
||||
if (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@expo/eas-json",
|
||||
"description": "A library for interacting with eas.json",
|
||||
"version": "16.1.0",
|
||||
"version": "16.7.0",
|
||||
"author": "Expo <[email protected]>",
|
||||
"bugs": "https://github.com/expo/eas-cli/issues",
|
||||
"dependencies": {
|
||||
|
||||
@@ -243,6 +243,7 @@
|
||||
"enum": [
|
||||
"auto",
|
||||
"latest",
|
||||
"sdk-52",
|
||||
"sdk-51",
|
||||
"sdk-50",
|
||||
"sdk-49",
|
||||
@@ -255,6 +256,7 @@
|
||||
"markdownEnumDescriptions": [
|
||||
"When using this option the build image is selected automatically based on the project configuration, detected Expo SDK and React Native versions.",
|
||||
"The latest Android image currently available. It is resolved to `ubuntu-22.04-jdk-17-ndk-r26b`. The `latest` to image mapping will be updated as new images are released.",
|
||||
"The recommended image for SDK 52 builds",
|
||||
"The recommended image for SDK 51 builds",
|
||||
"The recommended image for SDK 50 builds",
|
||||
"The recommended image for SDK 49 builds"
|
||||
|
||||
@@ -14,4 +14,8 @@ export const EasJsonSchema = Joi.object({
|
||||
}),
|
||||
build: Joi.object().pattern(Joi.string(), BuildProfileSchema),
|
||||
submit: Joi.object().pattern(Joi.string(), UnresolvedSubmitProfileSchema),
|
||||
update: Joi.object({
|
||||
assetHostOverride: Joi.string(),
|
||||
manifestHostOverride: Joi.string(),
|
||||
}),
|
||||
});
|
||||
@@ -25,4 +25,8 @@ export interface EasJson {
|
||||
};
|
||||
build?: { [profileName: string]: EasJsonBuildProfile };
|
||||
submit?: { [profileName: string]: EasJsonSubmitProfile };
|
||||
update?: {
|
||||
assetHostOverride?: string;
|
||||
manifestHostOverride?: string;
|
||||
};
|
||||
}
|
||||
@@ -102,6 +102,20 @@ export class EasJsonUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static async getUpdateConfigAsync(
|
||||
accessor: EasJsonAccessor
|
||||
): Promise<EasJson['update'] | null> {
|
||||
try {
|
||||
const easJson = await accessor.readAsync();
|
||||
return easJson.update ?? null;
|
||||
} catch (err: any) {
|
||||
if (err instanceof MissingEasJsonError) {
|
||||
return null;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
public static async getSubmitProfileNamesAsync(accessor: EasJsonAccessor): Promise<string[]> {
|
||||
const easJson = await accessor.readAsync();
|
||||
return Object.keys(easJson?.submit ?? {});
|
||||
|
||||
@@ -1410,6 +1410,26 @@
|
||||
xcode "^3.0.1"
|
||||
xml2js "0.6.0"
|
||||
|
||||
"@expo/config-plugins@~10.0.2":
|
||||
version "10.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-10.0.2.tgz#040867991e9c8c527b4f5c13a47bcf040a7479fe"
|
||||
integrity sha512-TzUn3pPdpwCS0yYaSlZOClgDmCX8N4I2lfgitX5oStqmvpPtB+vqtdyqsVM02fQ2tlJIAqwBW+NHaHqqy8Jv7g==
|
||||
dependencies:
|
||||
"@expo/config-types" "^53.0.3"
|
||||
"@expo/json-file" "~9.1.4"
|
||||
"@expo/plist" "^0.3.4"
|
||||
"@expo/sdk-runtime-versions" "^1.0.0"
|
||||
chalk "^4.1.2"
|
||||
debug "^4.3.5"
|
||||
getenv "^1.0.0"
|
||||
glob "^10.4.2"
|
||||
resolve-from "^5.0.0"
|
||||
semver "^7.5.4"
|
||||
slash "^3.0.0"
|
||||
slugify "^1.6.6"
|
||||
xcode "^3.0.1"
|
||||
xml2js "0.6.0"
|
||||
|
||||
"@expo/config-plugins@~9.0.0":
|
||||
version "9.0.9"
|
||||
resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-9.0.9.tgz#3765c310c112e200c6715365d6023f6a05b001ed"
|
||||
@@ -1435,6 +1455,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-52.0.1.tgz#327af1b72a3a9d4556f41e083e0e284dd8198b96"
|
||||
integrity sha512-vD8ZetyKV7U29lR6+NJohYeoLYTH+eNYXJeNiSOrWCz0witJYY11meMmEnpEaVbN89EfC6uauSUOa6wihtbyPQ==
|
||||
|
||||
"@expo/config-types@^53.0.3", "@expo/config-types@^53.0.4":
|
||||
version "53.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-53.0.4.tgz#fe64fac734531ae883d18529b32586c23ffb1ceb"
|
||||
integrity sha512-0s+9vFx83WIToEr0Iwy4CcmiUXa5BgwBmEjylBB2eojX5XAMm9mJvw9KpjAb8m7zq2G0Q6bRbeufkzgbipuNQg==
|
||||
|
||||
"@expo/[email protected]":
|
||||
version "10.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@expo/config/-/config-10.0.6.tgz#85830491bc8cce2af3f19276922a13f5578d2aa8"
|
||||
@@ -1454,6 +1479,25 @@
|
||||
slugify "^1.3.4"
|
||||
sucrase "3.35.0"
|
||||
|
||||
"@expo/[email protected]":
|
||||
version "11.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@expo/config/-/config-11.0.10.tgz#559d9425a4e0de4fab96ccac01ff40f5cebbc04b"
|
||||
integrity sha512-8S8Krr/c5lnl0eF03tA2UGY9rGBhZcbWKz2UWw5dpL/+zstwUmog8oyuuC8aRcn7GiTQLlbBkxcMeT8sOGlhbA==
|
||||
dependencies:
|
||||
"@babel/code-frame" "~7.10.4"
|
||||
"@expo/config-plugins" "~10.0.2"
|
||||
"@expo/config-types" "^53.0.4"
|
||||
"@expo/json-file" "^9.1.4"
|
||||
deepmerge "^4.3.1"
|
||||
getenv "^1.0.0"
|
||||
glob "^10.4.2"
|
||||
require-from-string "^2.0.2"
|
||||
resolve-from "^5.0.0"
|
||||
resolve-workspace-root "^2.0.0"
|
||||
semver "^7.6.0"
|
||||
slugify "^1.3.4"
|
||||
sucrase "3.35.0"
|
||||
|
||||
"@expo/config@~10.0.4":
|
||||
version "10.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@expo/config/-/config-10.0.4.tgz#a58ec3baef123e77584fbae769484bae2ee74f37"
|
||||
@@ -1528,6 +1572,14 @@
|
||||
json5 "^2.2.3"
|
||||
write-file-atomic "^2.3.0"
|
||||
|
||||
"@expo/json-file@^9.1.4", "@expo/json-file@~9.1.4":
|
||||
version "9.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-9.1.4.tgz#e719d092c08afb3234643f9285e57c6a24989327"
|
||||
integrity sha512-7Bv86X27fPERGhw8aJEZvRcH9sk+9BenDnEmrI3ZpywKodYSBgc8lX9Y32faNVQ/p0YbDK9zdJ0BfAKNAOyi0A==
|
||||
dependencies:
|
||||
"@babel/code-frame" "~7.10.4"
|
||||
json5 "^2.2.3"
|
||||
|
||||
"@expo/[email protected]":
|
||||
version "1.0.117"
|
||||
resolved "https://registry.yarnpkg.com/@expo/logger/-/logger-1.0.117.tgz#31e302656f33dd015fdde89ad803d710a0e5b8a2"
|
||||
@@ -1585,6 +1637,15 @@
|
||||
base64-js "^1.2.3"
|
||||
xmlbuilder "^14.0.0"
|
||||
|
||||
"@expo/plist@^0.3.4":
|
||||
version "0.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.3.4.tgz#0c48eeff2158cf26c5c9ed4f681d24997ccfbeca"
|
||||
integrity sha512-MhBLaUJNe9FQDDU2xhSNS4SAolr6K2wuyi4+A79vYuXLkAoICsbTwcGEQJN5jPY6D9izO/jsXh5k0h+mIWQMdw==
|
||||
dependencies:
|
||||
"@xmldom/xmldom" "^0.8.8"
|
||||
base64-js "^1.2.3"
|
||||
xmlbuilder "^15.1.1"
|
||||
|
||||
"@expo/[email protected]":
|
||||
version "5.1.23"
|
||||
resolved "https://registry.yarnpkg.com/@expo/plugin-help/-/plugin-help-5.1.23.tgz#36d82111ec6c0e9870a3f0856ae7536186624912"
|
||||
@@ -4145,6 +4206,11 @@
|
||||
fast-querystring "^1.1.1"
|
||||
tslib "^2.3.1"
|
||||
|
||||
"@xmldom/xmldom@^0.8.8":
|
||||
version "0.8.10"
|
||||
resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz#a1337ca426aa61cef9fe15b5b28e340a72f6fa99"
|
||||
integrity sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==
|
||||
|
||||
"@xmldom/xmldom@~0.7.7":
|
||||
version "0.7.9"
|
||||
resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.7.9.tgz#7f9278a50e737920e21b297b8a35286e9942c056"
|
||||
@@ -4904,6 +4970,13 @@ [email protected]:
|
||||
dependencies:
|
||||
big-integer "1.6.x"
|
||||
|
||||
bplist-parser@^0.3.0:
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.3.2.tgz#3ac79d67ec52c4c107893e0237eb787cbacbced7"
|
||||
integrity sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==
|
||||
dependencies:
|
||||
big-integer "1.6.x"
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
@@ -14758,6 +14831,11 @@ xmlbuilder@^14.0.0:
|
||||
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-14.0.0.tgz#876b5aec4f05ffd5feb97b0a871c855d16fbeb8c"
|
||||
integrity sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg==
|
||||
|
||||
xmlbuilder@^15.1.1:
|
||||
version "15.1.1"
|
||||
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5"
|
||||
integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==
|
||||
|
||||
xmlbuilder@^9.0.7, xmlbuilder@~9.0.1:
|
||||
version "9.0.7"
|
||||
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
|
||||
|
||||
Reference in new issue
Block a user