eas-cli 3.16.0 → 3.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -55
- package/build/build/build.js +1 -0
- package/build/build/errors.d.ts +2 -0
- package/build/build/errors.js +4 -1
- package/build/channel/branch-mapping.d.ts +27 -0
- package/build/channel/branch-mapping.js +49 -0
- package/build/channel/queries.d.ts +6 -1
- package/build/channel/queries.js +29 -3
- package/build/channel/utils.d.ts +3 -12
- package/build/channel/utils.js +24 -4
- package/build/commandUtils/context/contextUtils/createGraphqlClient.d.ts +2 -2
- package/build/commandUtils/context/contextUtils/createGraphqlClient.js +0 -1
- package/build/commands/channel/edit.d.ts +2 -2
- package/build/commands/channel/edit.js +4 -2
- package/build/commands/channel/rollout.js +6 -1
- package/build/credentials/android/api/graphql/mutations/AndroidAppBuildCredentialsMutation.js +2 -2
- package/build/graphql/generated.d.ts +180 -19
- package/build/graphql/generated.js +11 -2
- package/build/graphql/queries/ChannelQuery.d.ts +8 -4
- package/build/graphql/queries/ChannelQuery.js +43 -4
- package/build/graphql/types/Submission.js +1 -0
- package/build/graphql/types/UpdateChannelBasicInfo.d.ts +1 -0
- package/build/graphql/types/UpdateChannelBasicInfo.js +12 -0
- package/build/rollout/utils.d.ts +53 -0
- package/build/rollout/utils.js +105 -0
- package/build/submit/android/AndroidSubmitCommand.d.ts +1 -0
- package/build/submit/android/AndroidSubmitCommand.js +7 -1
- package/build/submit/android/AndroidSubmitter.d.ts +1 -1
- package/build/submit/android/AndroidSubmitter.js +5 -2
- package/build/utils/relay.d.ts +33 -0
- package/build/utils/relay.js +43 -0
- package/oclif.manifest.json +1 -1
- package/package.json +9 -8
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { BranchMapping } from '../channel/branch-mapping';
|
|
2
|
+
/**
|
|
3
|
+
* Detect if a branch mapping is a rollout.
|
|
4
|
+
*
|
|
5
|
+
* Types of rollout:
|
|
6
|
+
* 1. Legacy unconstrained rollout:
|
|
7
|
+
* Maps to a rollout branch via a rollout token
|
|
8
|
+
* Falls back to a default branch
|
|
9
|
+
*
|
|
10
|
+
* Example:
|
|
11
|
+
* {
|
|
12
|
+
version: 0,
|
|
13
|
+
data: [
|
|
14
|
+
{
|
|
15
|
+
branchId: uuidv4(),
|
|
16
|
+
branchMappingLogic: {
|
|
17
|
+
operand: 10 / 100,
|
|
18
|
+
clientKey: 'rolloutToken',
|
|
19
|
+
branchMappingOperator: hashLtOperator(),
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
{ branchId: uuidv4(), branchMappingLogic: alwaysTrue() },
|
|
23
|
+
],
|
|
24
|
+
}
|
|
25
|
+
*
|
|
26
|
+
* 2. RTV constrained rollout:
|
|
27
|
+
* Maps to a rollout branch via a rollout token, constrained by runtime version
|
|
28
|
+
* Falls back to a default branch
|
|
29
|
+
*
|
|
30
|
+
* Example:
|
|
31
|
+
* {
|
|
32
|
+
version: 0,
|
|
33
|
+
data: [
|
|
34
|
+
{
|
|
35
|
+
branchId: uuidv4(),
|
|
36
|
+
branchMappingLogic: andStatement([
|
|
37
|
+
{
|
|
38
|
+
operand: '1.0.0',
|
|
39
|
+
clientKey: 'runtimeVersion',
|
|
40
|
+
branchMappingOperator: equalsOperator(),
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
operand: 10 / 100,
|
|
44
|
+
clientKey: 'rolloutToken',
|
|
45
|
+
branchMappingOperator: hashLtOperator(),
|
|
46
|
+
},
|
|
47
|
+
]),
|
|
48
|
+
},
|
|
49
|
+
{ branchId: uuidv4(), branchMappingLogic: alwaysTrue() },
|
|
50
|
+
],
|
|
51
|
+
}
|
|
52
|
+
*/
|
|
53
|
+
export declare function isRollout(branchMapping: BranchMapping): boolean;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isRollout = void 0;
|
|
4
|
+
const branch_mapping_1 = require("../channel/branch-mapping");
|
|
5
|
+
/**
|
|
6
|
+
* Detect if a branch mapping is a rollout.
|
|
7
|
+
*
|
|
8
|
+
* Types of rollout:
|
|
9
|
+
* 1. Legacy unconstrained rollout:
|
|
10
|
+
* Maps to a rollout branch via a rollout token
|
|
11
|
+
* Falls back to a default branch
|
|
12
|
+
*
|
|
13
|
+
* Example:
|
|
14
|
+
* {
|
|
15
|
+
version: 0,
|
|
16
|
+
data: [
|
|
17
|
+
{
|
|
18
|
+
branchId: uuidv4(),
|
|
19
|
+
branchMappingLogic: {
|
|
20
|
+
operand: 10 / 100,
|
|
21
|
+
clientKey: 'rolloutToken',
|
|
22
|
+
branchMappingOperator: hashLtOperator(),
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
{ branchId: uuidv4(), branchMappingLogic: alwaysTrue() },
|
|
26
|
+
],
|
|
27
|
+
}
|
|
28
|
+
*
|
|
29
|
+
* 2. RTV constrained rollout:
|
|
30
|
+
* Maps to a rollout branch via a rollout token, constrained by runtime version
|
|
31
|
+
* Falls back to a default branch
|
|
32
|
+
*
|
|
33
|
+
* Example:
|
|
34
|
+
* {
|
|
35
|
+
version: 0,
|
|
36
|
+
data: [
|
|
37
|
+
{
|
|
38
|
+
branchId: uuidv4(),
|
|
39
|
+
branchMappingLogic: andStatement([
|
|
40
|
+
{
|
|
41
|
+
operand: '1.0.0',
|
|
42
|
+
clientKey: 'runtimeVersion',
|
|
43
|
+
branchMappingOperator: equalsOperator(),
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
operand: 10 / 100,
|
|
47
|
+
clientKey: 'rolloutToken',
|
|
48
|
+
branchMappingOperator: hashLtOperator(),
|
|
49
|
+
},
|
|
50
|
+
]),
|
|
51
|
+
},
|
|
52
|
+
{ branchId: uuidv4(), branchMappingLogic: alwaysTrue() },
|
|
53
|
+
],
|
|
54
|
+
}
|
|
55
|
+
*/
|
|
56
|
+
function isRollout(branchMapping) {
|
|
57
|
+
return isUnconstrainedRollout(branchMapping) || isRtvConstrainedRollout(branchMapping);
|
|
58
|
+
}
|
|
59
|
+
exports.isRollout = isRollout;
|
|
60
|
+
function isRtvConstrainedRollout(branchMapping) {
|
|
61
|
+
if (branchMapping.data.length !== 2) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
const hasRtvRolloutNode = isRtvConstrainedRolloutNode(branchMapping.data[0].branchMappingLogic);
|
|
65
|
+
const defaultsToAlwaysTrueNode = (0, branch_mapping_1.isAlwaysTrue)(branchMapping.data[1].branchMappingLogic);
|
|
66
|
+
return hasRtvRolloutNode && defaultsToAlwaysTrueNode;
|
|
67
|
+
}
|
|
68
|
+
function isRtvConstrainedRolloutNode(node) {
|
|
69
|
+
if (!(0, branch_mapping_1.isStatement)(node) || !(0, branch_mapping_1.isAndStatement)(node)) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
const statementNodes = (0, branch_mapping_1.getNodesFromStatement)(node);
|
|
73
|
+
if (statementNodes.length !== 2) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
const hasRuntimeVersionNode = statementNodes.some(isRuntimeVersionNode);
|
|
77
|
+
const hasRolloutNode = statementNodes.some(isRolloutNode);
|
|
78
|
+
return hasRuntimeVersionNode && hasRolloutNode;
|
|
79
|
+
}
|
|
80
|
+
function isUnconstrainedRollout(branchMapping) {
|
|
81
|
+
if (branchMapping.data.length !== 2) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
const hasRolloutNode = isRolloutNode(branchMapping.data[0].branchMappingLogic);
|
|
85
|
+
const defaultsToAlwaysTrueNode = (0, branch_mapping_1.isAlwaysTrue)(branchMapping.data[1].branchMappingLogic);
|
|
86
|
+
return hasRolloutNode && defaultsToAlwaysTrueNode;
|
|
87
|
+
}
|
|
88
|
+
function isRuntimeVersionNode(node) {
|
|
89
|
+
if (typeof node === 'string') {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
if (Array.isArray(node)) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
return node.clientKey === 'runtimeVersion' && node.branchMappingOperator === '==';
|
|
96
|
+
}
|
|
97
|
+
function isRolloutNode(node) {
|
|
98
|
+
if (typeof node === 'string') {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
if (Array.isArray(node)) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
return node.clientKey === 'rolloutToken' && node.branchMappingOperator === 'hash_lt';
|
|
105
|
+
}
|
|
@@ -9,6 +9,7 @@ export default class AndroidSubmitCommand {
|
|
|
9
9
|
private maybeGetAndroidPackageFromCurrentProjectAsync;
|
|
10
10
|
private resolveTrack;
|
|
11
11
|
private resolveReleaseStatus;
|
|
12
|
+
private resolveRollout;
|
|
12
13
|
private resolveArchiveSource;
|
|
13
14
|
private resolveServiceAccountSourceAsync;
|
|
14
15
|
}
|
|
@@ -24,8 +24,9 @@ class AndroidSubmitCommand {
|
|
|
24
24
|
const track = this.resolveTrack();
|
|
25
25
|
const releaseStatus = this.resolveReleaseStatus();
|
|
26
26
|
const archiveSource = this.resolveArchiveSource();
|
|
27
|
+
const rollout = this.resolveRollout();
|
|
27
28
|
const serviceAccountSource = await this.resolveServiceAccountSourceAsync();
|
|
28
|
-
const errored = [track, releaseStatus, archiveSource, serviceAccountSource].filter(r => !r.ok);
|
|
29
|
+
const errored = [track, releaseStatus, archiveSource, serviceAccountSource, rollout].filter(r => !r.ok);
|
|
29
30
|
if (errored.length > 0) {
|
|
30
31
|
const message = errored.map(err => { var _a; return (_a = err.reason) === null || _a === void 0 ? void 0 : _a.message; }).join('\n');
|
|
31
32
|
log_1.default.error(message);
|
|
@@ -35,6 +36,7 @@ class AndroidSubmitCommand {
|
|
|
35
36
|
projectId: this.ctx.projectId,
|
|
36
37
|
track: track.enforceValue(),
|
|
37
38
|
releaseStatus: releaseStatus.enforceValue(),
|
|
39
|
+
rollout: rollout.enforceValue(),
|
|
38
40
|
archiveSource: archiveSource.enforceValue(),
|
|
39
41
|
serviceAccountSource: serviceAccountSource.enforceValue(),
|
|
40
42
|
changesNotSentForReview: this.ctx.profile.changesNotSentForReview,
|
|
@@ -78,6 +80,10 @@ class AndroidSubmitCommand {
|
|
|
78
80
|
return (0, results_1.result)(new Error(`Unsupported release status: ${releaseStatus} (valid options: ${Object.keys(eas_json_1.AndroidReleaseStatus).join(', ')})`));
|
|
79
81
|
}
|
|
80
82
|
}
|
|
83
|
+
resolveRollout() {
|
|
84
|
+
const { rollout } = this.ctx.profile;
|
|
85
|
+
return (0, results_1.result)(rollout);
|
|
86
|
+
}
|
|
81
87
|
resolveArchiveSource() {
|
|
82
88
|
try {
|
|
83
89
|
return (0, results_1.result)((0, commons_1.resolveArchiveSource)(this.ctx));
|
|
@@ -4,7 +4,7 @@ import { ArchiveSource, ResolvedArchiveSource } from '../ArchiveSource';
|
|
|
4
4
|
import BaseSubmitter, { SubmissionInput } from '../BaseSubmitter';
|
|
5
5
|
import { SubmissionContext } from '../context';
|
|
6
6
|
import { ServiceAccountKeyResult, ServiceAccountSource } from './ServiceAccountSource';
|
|
7
|
-
export interface AndroidSubmissionOptions extends Pick<AndroidSubmissionConfigInput, 'track' | 'releaseStatus' | 'changesNotSentForReview'> {
|
|
7
|
+
export interface AndroidSubmissionOptions extends Pick<AndroidSubmissionConfigInput, 'track' | 'releaseStatus' | 'changesNotSentForReview' | 'rollout'> {
|
|
8
8
|
projectId: string;
|
|
9
9
|
archiveSource: ArchiveSource;
|
|
10
10
|
serviceAccountSource: ServiceAccountSource;
|
|
@@ -57,16 +57,17 @@ class AndroidSubmitter extends BaseSubmitter_1.default {
|
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
59
|
formatSubmissionConfig(options, { serviceAccountKeyResult }) {
|
|
60
|
-
const { track, releaseStatus, changesNotSentForReview } = options;
|
|
60
|
+
const { track, releaseStatus, changesNotSentForReview, rollout } = options;
|
|
61
61
|
return {
|
|
62
62
|
track,
|
|
63
63
|
changesNotSentForReview,
|
|
64
64
|
releaseStatus,
|
|
65
|
+
rollout,
|
|
65
66
|
...serviceAccountKeyResult.result,
|
|
66
67
|
};
|
|
67
68
|
}
|
|
68
69
|
prepareSummaryData(options, { archive, serviceAccountKeyResult }) {
|
|
69
|
-
const { projectId, track, releaseStatus, changesNotSentForReview } = options;
|
|
70
|
+
const { projectId, track, releaseStatus, changesNotSentForReview, rollout } = options;
|
|
70
71
|
// structuring order affects table rows order
|
|
71
72
|
return {
|
|
72
73
|
projectId,
|
|
@@ -74,6 +75,7 @@ class AndroidSubmitter extends BaseSubmitter_1.default {
|
|
|
74
75
|
changesNotSentForReview: changesNotSentForReview !== null && changesNotSentForReview !== void 0 ? changesNotSentForReview : undefined,
|
|
75
76
|
releaseStatus: releaseStatus !== null && releaseStatus !== void 0 ? releaseStatus : undefined,
|
|
76
77
|
formattedServiceAccount: formatServiceAccountSummary(serviceAccountKeyResult),
|
|
78
|
+
rollout: rollout !== null && rollout !== void 0 ? rollout : undefined,
|
|
77
79
|
...(0, summary_1.formatArchiveSourceSummary)(archive),
|
|
78
80
|
};
|
|
79
81
|
}
|
|
@@ -87,6 +89,7 @@ const SummaryHumanReadableKeys = {
|
|
|
87
89
|
formattedServiceAccount: 'Google Service Account Key',
|
|
88
90
|
projectId: 'Project ID',
|
|
89
91
|
releaseStatus: 'Release status',
|
|
92
|
+
rollout: 'Rollout',
|
|
90
93
|
track: 'Release track',
|
|
91
94
|
};
|
|
92
95
|
function formatServiceAccountSummary({ summary }) {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { PageInfo } from '../graphql/generated';
|
|
2
|
+
export type Connection<T> = {
|
|
3
|
+
edges: Edge<T>[];
|
|
4
|
+
pageInfo: PageInfo;
|
|
5
|
+
};
|
|
6
|
+
type Edge<T> = {
|
|
7
|
+
node: T;
|
|
8
|
+
};
|
|
9
|
+
export type QueryParams = {
|
|
10
|
+
first: number;
|
|
11
|
+
after?: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Fetches dataset in paginated manner (batch by batch) using GraphQL queries.
|
|
15
|
+
*
|
|
16
|
+
* @param queryAsync A promise based function for querying.
|
|
17
|
+
* @param beforeEachQuery Optional. A callback function to be called before each query
|
|
18
|
+
* @param afterEachQuery Optional. A callback function to be called after each query.
|
|
19
|
+
* @param filterPredicate Optional. A predicate function to filter the node.
|
|
20
|
+
* @param batchSize Optional. The batch size of the pagination. Defaults to 100.
|
|
21
|
+
*
|
|
22
|
+
* @return {Promise<T[]>} - A promise that resolves to an array (the dataset).
|
|
23
|
+
* @throws {Error} - If an error occurs during execution of the query or pagination.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getPaginatedDatasetAsync<T>({ queryAsync, beforeEachQuery, afterEachQuery, filterPredicate, batchSize, maxNodesFetched, }: {
|
|
26
|
+
queryAsync: ({ first, after }: QueryParams) => Promise<Connection<T>>;
|
|
27
|
+
beforeEachQuery?: (totalNodesFetched: number, dataset: T[]) => void;
|
|
28
|
+
afterEachQuery?: (totalNodesFetched: number, dataset: T[], batch: T[], pageInfo: PageInfo) => void;
|
|
29
|
+
filterPredicate?: (node: T) => boolean;
|
|
30
|
+
batchSize?: number;
|
|
31
|
+
maxNodesFetched?: number;
|
|
32
|
+
}): Promise<T[]>;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getPaginatedDatasetAsync = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Fetches dataset in paginated manner (batch by batch) using GraphQL queries.
|
|
6
|
+
*
|
|
7
|
+
* @param queryAsync A promise based function for querying.
|
|
8
|
+
* @param beforeEachQuery Optional. A callback function to be called before each query
|
|
9
|
+
* @param afterEachQuery Optional. A callback function to be called after each query.
|
|
10
|
+
* @param filterPredicate Optional. A predicate function to filter the node.
|
|
11
|
+
* @param batchSize Optional. The batch size of the pagination. Defaults to 100.
|
|
12
|
+
*
|
|
13
|
+
* @return {Promise<T[]>} - A promise that resolves to an array (the dataset).
|
|
14
|
+
* @throws {Error} - If an error occurs during execution of the query or pagination.
|
|
15
|
+
*/
|
|
16
|
+
async function getPaginatedDatasetAsync({ queryAsync, beforeEachQuery, afterEachQuery, filterPredicate, batchSize = 100, maxNodesFetched = 10000, }) {
|
|
17
|
+
var _a;
|
|
18
|
+
const dataset = [];
|
|
19
|
+
let hasMore = true;
|
|
20
|
+
let after;
|
|
21
|
+
let totalNodesFetched = 0;
|
|
22
|
+
while (hasMore) {
|
|
23
|
+
if (beforeEachQuery) {
|
|
24
|
+
beforeEachQuery(totalNodesFetched, dataset);
|
|
25
|
+
}
|
|
26
|
+
const result = await queryAsync({ first: batchSize, after });
|
|
27
|
+
const { edges, pageInfo } = result;
|
|
28
|
+
const nodes = edges.map(edge => edge.node);
|
|
29
|
+
const batch = filterPredicate ? nodes.filter(filterPredicate) : nodes;
|
|
30
|
+
dataset.push(...batch);
|
|
31
|
+
hasMore = pageInfo.hasNextPage;
|
|
32
|
+
after = (_a = pageInfo.endCursor) !== null && _a !== void 0 ? _a : undefined;
|
|
33
|
+
totalNodesFetched += nodes.length;
|
|
34
|
+
if (afterEachQuery) {
|
|
35
|
+
afterEachQuery(totalNodesFetched, dataset, batch, pageInfo);
|
|
36
|
+
}
|
|
37
|
+
if (totalNodesFetched >= maxNodesFetched) {
|
|
38
|
+
return dataset;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return dataset;
|
|
42
|
+
}
|
|
43
|
+
exports.getPaginatedDatasetAsync = getPaginatedDatasetAsync;
|