eoas 3.2.3-beta1 → 3.2.4
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.
|
@@ -16,6 +16,7 @@ export default class Publish extends Command {
|
|
|
16
16
|
dumpSourcemap: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
17
17
|
'rollout-percentage': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
18
18
|
'upload-rate': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
|
+
emitMetadata: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
19
20
|
};
|
|
20
21
|
private sanitizeFlags;
|
|
21
22
|
run(): Promise<void>;
|
package/dist/commands/publish.js
CHANGED
|
@@ -20,6 +20,7 @@ const prompts_1 = require("../lib/prompts");
|
|
|
20
20
|
const rateLimiter_1 = require("../lib/rateLimiter");
|
|
21
21
|
const repo_1 = require("../lib/repo");
|
|
22
22
|
const runtimeVersion_1 = require("../lib/runtimeVersion");
|
|
23
|
+
const updateMetadata_1 = require("../lib/updateMetadata");
|
|
23
24
|
const vcs_1 = require("../lib/vcs");
|
|
24
25
|
const workflow_1 = require("../lib/workflow");
|
|
25
26
|
class Publish extends core_1.Command {
|
|
@@ -84,6 +85,10 @@ class Publish extends core_1.Command {
|
|
|
84
85
|
description: 'Maximum number of asset uploads started per second. Accepts decimals (e.g. 1.5). Lower this if your storage provider rate-limits uploads.',
|
|
85
86
|
default: '10',
|
|
86
87
|
}),
|
|
88
|
+
emitMetadata: core_1.Flags.boolean({
|
|
89
|
+
description: `Emit "${updateMetadata_1.UPDATE_METADATA_FILE}" in the output directory with the published update of each platform`,
|
|
90
|
+
default: false,
|
|
91
|
+
}),
|
|
87
92
|
};
|
|
88
93
|
sanitizeFlags(flags) {
|
|
89
94
|
const uploadRate = Number(flags['upload-rate']);
|
|
@@ -104,6 +109,7 @@ class Publish extends core_1.Command {
|
|
|
104
109
|
dumpSourcemap: flags.dumpSourcemap,
|
|
105
110
|
rolloutPercentage: flags['rollout-percentage'],
|
|
106
111
|
uploadRate,
|
|
112
|
+
emitMetadata: flags.emitMetadata,
|
|
107
113
|
};
|
|
108
114
|
}
|
|
109
115
|
async run() {
|
|
@@ -113,7 +119,7 @@ class Publish extends core_1.Command {
|
|
|
113
119
|
process.exit(1);
|
|
114
120
|
}
|
|
115
121
|
const { flags } = await this.parse(Publish);
|
|
116
|
-
const { platform, nonInteractive, branch, customServerUrl, outputDir, packageRunner, providedDeprecatedChannel, disableRepositoryCheck, message, dumpSourcemap, rolloutPercentage, uploadRate, } = this.sanitizeFlags(flags);
|
|
122
|
+
const { platform, nonInteractive, branch, customServerUrl, outputDir, packageRunner, providedDeprecatedChannel, disableRepositoryCheck, message, dumpSourcemap, rolloutPercentage, uploadRate, emitMetadata, } = this.sanitizeFlags(flags);
|
|
117
123
|
if (!branch) {
|
|
118
124
|
log_1.default.error('Branch name is required');
|
|
119
125
|
process.exit(1);
|
|
@@ -264,6 +270,20 @@ class Publish extends core_1.Command {
|
|
|
264
270
|
uploadFilesSpinner.fail('No files to upload');
|
|
265
271
|
process.exit(1);
|
|
266
272
|
}
|
|
273
|
+
const platformsToUpload = [];
|
|
274
|
+
const missingBundlePlatforms = [];
|
|
275
|
+
for (const runtime of runtimeVersions) {
|
|
276
|
+
if (files.some(file => file.platform === runtime.platform && file.isLaunchAsset)) {
|
|
277
|
+
platformsToUpload.push(runtime);
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
missingBundlePlatforms.push(runtime.platform);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (!platformsToUpload.length) {
|
|
284
|
+
uploadFilesSpinner.fail('No platforms with a bundle to upload');
|
|
285
|
+
process.exit(1);
|
|
286
|
+
}
|
|
267
287
|
let uploadUrls = [];
|
|
268
288
|
// One group id for the whole run: every platform update of this publish
|
|
269
289
|
// shares it, so control plane servers list them as a single publish.
|
|
@@ -272,7 +292,7 @@ class Publish extends core_1.Command {
|
|
|
272
292
|
// running spinner interleaves with its frames.
|
|
273
293
|
const unchangedPlatforms = [];
|
|
274
294
|
try {
|
|
275
|
-
const outcomes = await Promise.all(
|
|
295
|
+
const outcomes = await Promise.all(platformsToUpload.map(async ({ runtimeVersion, platform }) => {
|
|
276
296
|
if (!runtimeVersion) {
|
|
277
297
|
throw new Error('Runtime version is not resolved');
|
|
278
298
|
}
|
|
@@ -307,6 +327,9 @@ class Publish extends core_1.Command {
|
|
|
307
327
|
});
|
|
308
328
|
if (!uploadUrls.length) {
|
|
309
329
|
uploadFilesSpinner.warn('⚠️ No changes found in the update, nothing to deploy');
|
|
330
|
+
for (const skipped of missingBundlePlatforms) {
|
|
331
|
+
log_1.default.withInfo(`⚠️ No bundle exported for ${skipped}, skipping.`);
|
|
332
|
+
}
|
|
310
333
|
return;
|
|
311
334
|
}
|
|
312
335
|
// Every path and URL the server handed back is checked here, before a
|
|
@@ -384,6 +407,9 @@ class Publish extends core_1.Command {
|
|
|
384
407
|
for (const skipped of unchangedPlatforms) {
|
|
385
408
|
log_1.default.withInfo(`⚠️ There is no change in the update for ${skipped}, ignored...`);
|
|
386
409
|
}
|
|
410
|
+
for (const skipped of missingBundlePlatforms) {
|
|
411
|
+
log_1.default.withInfo(`⚠️ No bundle exported for ${skipped}, skipping.`);
|
|
412
|
+
}
|
|
387
413
|
}
|
|
388
414
|
catch (e) {
|
|
389
415
|
uploadFilesSpinner.fail('❌ Failed to upload static files');
|
|
@@ -391,6 +417,7 @@ class Publish extends core_1.Command {
|
|
|
391
417
|
process.exit(1);
|
|
392
418
|
}
|
|
393
419
|
const markAsFinishedSpinner = (0, ora_1.ora)('🔗 Marking the updates as finished...').start();
|
|
420
|
+
const publishedUpdateUUIDs = {};
|
|
394
421
|
const results = await Promise.all(uploadUrls.map(async ({ updateId, platform, runtimeVersion, rolloutPercentage: echoedRolloutPercentage, }) => {
|
|
395
422
|
const markAsUploadedUrl = new URL(`${serverUrl}/${appId}/markUpdateAsUploaded/${branch}`);
|
|
396
423
|
markAsUploadedUrl.searchParams.set('platform', platform);
|
|
@@ -405,6 +432,7 @@ class Publish extends core_1.Command {
|
|
|
405
432
|
});
|
|
406
433
|
// If success and status code = 200
|
|
407
434
|
if (response.ok) {
|
|
435
|
+
publishedUpdateUUIDs[platform] = await (0, updateMetadata_1.readUpdateUUID)(response);
|
|
408
436
|
log_1.default.withInfo(`✅ Update ready for ${platform}`);
|
|
409
437
|
// Announce only when the server echoed the percentage back: an old server
|
|
410
438
|
// silently ignores the param and ships the update to 100% of devices.
|
|
@@ -463,6 +491,24 @@ class Publish extends core_1.Command {
|
|
|
463
491
|
// update has nothing to group anyway.
|
|
464
492
|
log_1.default.withInfo('ℹ️ Platform updates were published without grouping (publish groups require a server in control plane mode).');
|
|
465
493
|
}
|
|
494
|
+
if (emitMetadata) {
|
|
495
|
+
const deployed = uploadUrls.filter((_, index) => results[index] === 'deployed');
|
|
496
|
+
if (deployed.some(({ platform: p }) => !publishedUpdateUUIDs[p])) {
|
|
497
|
+
log_1.default.warn(`⚠️ ${updateMetadata_1.UPDATE_METADATA_FILE} was not written: the server did not return the update ids. Upgrade the server to use --emitMetadata.`);
|
|
498
|
+
}
|
|
499
|
+
else {
|
|
500
|
+
const metadata = deployed.map(u => ({
|
|
501
|
+
id: publishedUpdateUUIDs[u.platform],
|
|
502
|
+
platform: u.platform,
|
|
503
|
+
runtimeVersion: u.runtimeVersion,
|
|
504
|
+
branch,
|
|
505
|
+
group: groupAcknowledged ? publishGroupId : undefined,
|
|
506
|
+
message: resolvedMessage,
|
|
507
|
+
}));
|
|
508
|
+
await (0, updateMetadata_1.writeUpdateMetadata)(path_1.default.join(projectDir, outputDir), metadata);
|
|
509
|
+
log_1.default.withInfo(`📝 ${updateMetadata_1.UPDATE_METADATA_FILE} written to ${outputDir}`);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
466
512
|
log_1.default.withInfo('🔥 Your users will receive the latest update automatically!');
|
|
467
513
|
}
|
|
468
514
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const UPDATE_METADATA_FILE = "xprem-update-metadata.json";
|
|
2
|
+
export interface PublishedUpdateMetadata {
|
|
3
|
+
id: string;
|
|
4
|
+
platform: string;
|
|
5
|
+
runtimeVersion: string;
|
|
6
|
+
branch: string;
|
|
7
|
+
group?: string;
|
|
8
|
+
message?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function readUpdateUUID(response: {
|
|
11
|
+
text(): Promise<string>;
|
|
12
|
+
}): Promise<string | undefined>;
|
|
13
|
+
export declare function writeUpdateMetadata(exportDir: string, updates: PublishedUpdateMetadata[]): Promise<void>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.writeUpdateMetadata = exports.readUpdateUUID = exports.UPDATE_METADATA_FILE = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
6
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
7
|
+
exports.UPDATE_METADATA_FILE = 'xprem-update-metadata.json';
|
|
8
|
+
// readUpdateUUID reads the manifest id from a markUpdateAsUploaded response.
|
|
9
|
+
// Undefined when the server is too old to send one.
|
|
10
|
+
async function readUpdateUUID(response) {
|
|
11
|
+
try {
|
|
12
|
+
const { updateUUID } = JSON.parse(await response.text());
|
|
13
|
+
return typeof updateUUID === 'string' && updateUUID ? updateUUID : undefined;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.readUpdateUUID = readUpdateUUID;
|
|
20
|
+
async function writeUpdateMetadata(exportDir, updates) {
|
|
21
|
+
await fs_extra_1.default.writeJson(path_1.default.join(exportDir, exports.UPDATE_METADATA_FILE), updates, { spaces: 2 });
|
|
22
|
+
}
|
|
23
|
+
exports.writeUpdateMetadata = writeUpdateMetadata;
|