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>;
@@ -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(runtimeVersions.map(async ({ runtimeVersion, platform }) => {
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eoas",
3
- "version": "3.2.3-beta1",
3
+ "version": "3.2.4",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "build": "tsc --project tsconfig.json",