balena-cli 12.51.2 → 12.51.3

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.
@@ -1306,15 +1306,101 @@ async function getTokenForPreviousRepos(
1306
1306
  return token;
1307
1307
  }
1308
1308
 
1309
+ async function pushAndUpdateServiceImages(
1310
+ docker: Dockerode,
1311
+ token: string,
1312
+ images: TaggedImage[],
1313
+ afterEach: (
1314
+ serviceImage: import('balena-release/build/models').ImageModel,
1315
+ props: object,
1316
+ ) => void,
1317
+ ) {
1318
+ const { DockerProgress } = await import('docker-progress');
1319
+ const { retry } = await import('./helpers');
1320
+ const { pushProgressRenderer } = await import('./compose');
1321
+ const tty = (await import('./tty'))(process.stdout);
1322
+ const opts = { authconfig: { registrytoken: token } };
1323
+ const progress = new DockerProgress({ docker });
1324
+ const renderer = pushProgressRenderer(
1325
+ tty,
1326
+ getChalk().blue('[Push]') + ' ',
1327
+ );
1328
+ const reporters = progress.aggregateProgress(images.length, renderer);
1329
+
1330
+ const pushImage = async (
1331
+ localImage: Dockerode.Image,
1332
+ index: number,
1333
+ ): Promise<string> => {
1334
+ try {
1335
+ // TODO 'localImage as any': find out exactly why tsc warns about
1336
+ // 'name' that exists as a matter of fact, with a value similar to:
1337
+ // "name": "registry2.balena-cloud.com/v2/aa27790dff571ec7d2b4fbcf3d4648d5:latest"
1338
+ const imgName: string = (localImage as any).name || '';
1339
+ const imageDigest: string = await retry({
1340
+ func: () => progress.push(imgName, reporters[index], opts),
1341
+ maxAttempts: 3, // try calling func 3 times (max)
1342
+ label: imgName, // label for retry log messages
1343
+ initialDelayMs: 2000, // wait 2 seconds before the 1st retry
1344
+ backoffScaler: 1.4, // wait multiplier for each retry
1345
+ });
1346
+ if (!imageDigest) {
1347
+ throw new ExpectedError(stripIndent`\
1348
+ Unable to extract image digest (content hash) from image upload progress stream for image:
1349
+ ${imgName}`);
1350
+ }
1351
+ return imageDigest;
1352
+ } finally {
1353
+ renderer.end();
1354
+ }
1355
+ };
1356
+
1357
+ const inspectAndPushImage = async (
1358
+ { serviceImage, localImage, props, logs }: TaggedImage,
1359
+ index: number,
1360
+ ) => {
1361
+ try {
1362
+ const [imgInfo, imgDigest] = await Promise.all([
1363
+ localImage.inspect(),
1364
+ pushImage(localImage, index),
1365
+ ]);
1366
+ serviceImage.image_size = imgInfo.Size;
1367
+ serviceImage.content_hash = imgDigest;
1368
+ serviceImage.build_log = logs;
1369
+ serviceImage.dockerfile = props.dockerfile;
1370
+ serviceImage.project_type = props.projectType;
1371
+ if (props.startTime) {
1372
+ serviceImage.start_timestamp = props.startTime;
1373
+ }
1374
+ if (props.endTime) {
1375
+ serviceImage.end_timestamp = props.endTime;
1376
+ }
1377
+ serviceImage.push_timestamp = new Date();
1378
+ serviceImage.status = 'success';
1379
+ } catch (error) {
1380
+ serviceImage.error_message = '' + error;
1381
+ serviceImage.status = 'failed';
1382
+ throw error;
1383
+ } finally {
1384
+ await afterEach(serviceImage, props);
1385
+ }
1386
+ };
1387
+
1388
+ tty.hideCursor();
1389
+ try {
1390
+ await Promise.all(images.map(inspectAndPushImage));
1391
+ } finally {
1392
+ tty.showCursor();
1393
+ }
1394
+ }
1395
+
1309
1396
  async function pushServiceImages(
1310
- docker: import('dockerode'),
1397
+ docker: Dockerode,
1311
1398
  logger: Logger,
1312
1399
  pineClient: ReturnType<typeof import('balena-release').createClient>,
1313
1400
  taggedImages: TaggedImage[],
1314
1401
  token: string,
1315
1402
  skipLogUpload: boolean,
1316
1403
  ): Promise<void> {
1317
- const { pushAndUpdateServiceImages } = await import('./compose');
1318
1404
  const releaseMod = await import('balena-release');
1319
1405
  logger.logInfo('Pushing images to registry...');
1320
1406
  await pushAndUpdateServiceImages(
@@ -1337,7 +1423,7 @@ async function pushServiceImages(
1337
1423
  const PLAIN_SEMVER_REGEX = /^([0-9]+)\.([0-9]+)\.([0-9]+)$/;
1338
1424
 
1339
1425
  export async function deployProject(
1340
- docker: import('dockerode'),
1426
+ docker: Dockerode,
1341
1427
  logger: Logger,
1342
1428
  composition: Composition,
1343
1429
  images: BuiltImage[],
package/lib/utils/tty.ts CHANGED
@@ -1,3 +1,20 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2018-2021 Balena Ltd.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
1
18
  const windowSize: { width?: number; height?: number } = {};
2
19
 
3
20
  const updateWindowSize = () => {
@@ -29,13 +46,6 @@ export = (stream: NodeJS.WriteStream = process.stdout) => {
29
46
 
30
47
  const cursorDown = (rows: number = 0) => stream.write(`\u001B[${rows}B`);
31
48
 
32
- const cursorHidden = () => {
33
- const Bluebird = require('bluebird') as typeof import('bluebird');
34
- return Bluebird.try(hideCursor).disposer(() => {
35
- showCursor();
36
- });
37
- };
38
-
39
49
  const write = (str: string) => stream.write(str);
40
50
 
41
51
  const writeLine = (str: string) => stream.write(`${str}\n`);
@@ -54,7 +64,6 @@ export = (stream: NodeJS.WriteStream = process.stdout) => {
54
64
  currentWindowSize,
55
65
  hideCursor,
56
66
  showCursor,
57
- cursorHidden,
58
67
  cursorUp,
59
68
  cursorDown,
60
69
  write,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "balena-cli",
3
- "version": "12.51.2",
3
+ "version": "12.51.3",
4
4
  "lockfileVersion": 1,
5
5
  "requires": true,
6
6
  "dependencies": {