diff --git a/automation/build-bin.ts b/automation/build-bin.ts index 8e0b39c1..010d2b52 100644 --- a/automation/build-bin.ts +++ b/automation/build-bin.ts @@ -103,15 +103,17 @@ async function buildPkg() { ['*', ['opn', 'xdg-open'], ['xdg-open-402']], ['darwin', ['denymount', 'bin', 'denymount'], ['denymount']], ]; - await Bluebird.map(paths, ([platform, source, dest]) => { - if (platform === '*' || platform === process.platform) { - // eg copy from node_modules/open/xdg-open to build-bin/xdg-open - return fs.copy( - path.join(ROOT, 'node_modules', ...source), - path.join(ROOT, 'build-bin', ...dest), - ); - } - }); + await Promise.all( + paths.map(([platform, source, dest]) => { + if (platform === '*' || platform === process.platform) { + // eg copy from node_modules/open/xdg-open to build-bin/xdg-open + return fs.copy( + path.join(ROOT, 'node_modules', ...source), + path.join(ROOT, 'build-bin', ...dest), + ); + } + }), + ); const nativeExtensionPaths: string[] = await filehound .create() .paths(path.join(ROOT, 'node_modules')) @@ -120,12 +122,14 @@ async function buildPkg() { console.log(`\nCopying to build-bin:\n${nativeExtensionPaths.join('\n')}`); - await Bluebird.map(nativeExtensionPaths, (extPath) => - fs.copy( - extPath, - extPath.replace( - path.join(ROOT, 'node_modules'), - path.join(ROOT, 'build-bin'), + await Promise.all( + nativeExtensionPaths.map((extPath) => + fs.copy( + extPath, + extPath.replace( + path.join(ROOT, 'node_modules'), + path.join(ROOT, 'build-bin'), + ), ), ), ); diff --git a/lib/actions-oclif/os/configure.ts b/lib/actions-oclif/os/configure.ts index ecb20abd..6da3662c 100644 --- a/lib/actions-oclif/os/configure.ts +++ b/lib/actions-oclif/os/configure.ts @@ -17,7 +17,6 @@ import { flags } from '@oclif/command'; import type * as BalenaSdk from 'balena-sdk'; -import Bluebird = require('bluebird'); import * as _ from 'lodash'; import * as path from 'path'; import Command from '../../command'; @@ -263,9 +262,8 @@ export default class OsConfigureCmd extends Command { ); if (options['system-connection']) { - const files = await Bluebird.map( - options['system-connection'], - async (filePath) => { + const files = await Promise.all( + options['system-connection'].map(async (filePath) => { const content = await fs.readFile(filePath, 'utf8'); const name = path.basename(filePath); @@ -273,10 +271,10 @@ export default class OsConfigureCmd extends Command { name, content, }; - }, + }), ); - await Bluebird.each(files, async ({ name, content }) => { + for (const { name, content } of files) { await imagefs.writeFile( { image, @@ -286,7 +284,7 @@ export default class OsConfigureCmd extends Command { content, ); console.info(`Copied system-connection file: ${name}`); - }); + } } } } diff --git a/lib/actions-oclif/scan.ts b/lib/actions-oclif/scan.ts index 8024abe4..0740a47e 100644 --- a/lib/actions-oclif/scan.ts +++ b/lib/actions-oclif/scan.ts @@ -105,9 +105,8 @@ export default class ScanCmd extends Command { } // Query devices for info - const devicesInfo = await Bluebird.map( - activeLocalDevices, - ({ host, address }) => { + const devicesInfo = await Promise.all( + activeLocalDevices.map(({ host, address }) => { const docker = dockerUtils.createClient({ host: address, port: dockerPort, @@ -123,7 +122,7 @@ export default class ScanCmd extends Command { .versionAsync() .catchReturn('Could not get Docker version'), }); - }, + }), ); // Reduce properties if not --verbose diff --git a/lib/actions/build.js b/lib/actions/build.js index 4fa8adea..0ac4ce77 100644 --- a/lib/actions/build.js +++ b/lib/actions/build.js @@ -194,18 +194,18 @@ Examples: }) .then(function ([app, resolvedArch, resolvedDeviceType]) { - return Bluebird.join( + return Promise.all([ dockerUtils.getDocker(options), dockerUtils.generateBuildOpts(options), compose.generateOpts(options), - (docker, buildOpts, composeOpts) => - buildProject(docker, logger, composeOpts, { - app, - arch: resolvedArch, - deviceType: resolvedDeviceType, - buildEmulated: !!options.emulated, - buildOpts, - }), + ]).then(([docker, buildOpts, composeOpts]) => + buildProject(docker, logger, composeOpts, { + app, + arch: resolvedArch, + deviceType: resolvedDeviceType, + buildEmulated: !!options.emulated, + buildOpts, + }), ); }); }, diff --git a/lib/actions/deploy.js b/lib/actions/deploy.js index e0af7a48..51a6564d 100644 --- a/lib/actions/deploy.js +++ b/lib/actions/deploy.js @@ -150,22 +150,22 @@ const deployProject = function (docker, logger, composeOpts, opts) { sdk.models.release.get(releaseId, { $select: ['commit'] }), ); } - return Bluebird.join( + return Promise.all([ sdk.auth.getUserId(), sdk.auth.getToken(), sdk.settings.get('apiUrl'), - (userId, auth, apiEndpoint) => - $deployProject( - docker, - logger, - project.composition, - images, - opts.app.id, - userId, - `Bearer ${auth}`, - apiEndpoint, - !opts.shouldUploadLogs, - ), + ]).then(([userId, auth, apiEndpoint]) => + $deployProject( + docker, + logger, + project.composition, + images, + opts.app.id, + userId, + `Bearer ${auth}`, + apiEndpoint, + !opts.shouldUploadLogs, + ), ); }) ); @@ -302,20 +302,20 @@ Examples: }) .then(() => helpers.getAppWithArch(appName)) .then(function (app) { - return Bluebird.join( + return Promise.all([ dockerUtils.getDocker(options), dockerUtils.generateBuildOpts(options), compose.generateOpts(options), - (docker, buildOpts, composeOpts) => - deployProject(docker, logger, composeOpts, { - app, - appName, // may be prefixed by 'owner/', unlike app.app_name - image, - shouldPerformBuild: !!options.build, - shouldUploadLogs: !options.nologupload, - buildEmulated: !!options.emulated, - buildOpts, - }), + ]).then(([docker, buildOpts, composeOpts]) => + deployProject(docker, logger, composeOpts, { + app, + appName, // may be prefixed by 'owner/', unlike app.app_name + image, + shouldPerformBuild: !!options.build, + shouldUploadLogs: !options.nologupload, + buildEmulated: !!options.emulated, + buildOpts, + }), ); }); }, diff --git a/lib/actions/preload.js b/lib/actions/preload.js index 48ca0e11..1fd9b0ee 100644 --- a/lib/actions/preload.js +++ b/lib/actions/preload.js @@ -255,8 +255,6 @@ Examples: primary: true, options: preloadOptions, action(params, options, done) { - let certificates; - const Bluebird = require('bluebird'); const balena = getBalenaSdk(); const balenaPreload = require('balena-preload'); const visuals = getVisuals(); @@ -309,6 +307,7 @@ Examples: options.pinDevice = options['pin-device-to-release'] || false; delete options['pin-device-to-release']; + let certificates; if (Array.isArray(options['add-certificate'])) { certificates = options['add-certificate']; } else if (options['add-certificate'] === undefined) { @@ -358,7 +357,7 @@ Examples: preloader.on('progress', progressHandler); preloader.on('spinner', spinnerHandler); - return new Bluebird(function (resolve, reject) { + return new Promise(function (resolve, reject) { preloader.on('error', reject); return preloader diff --git a/lib/actions/push.ts b/lib/actions/push.ts index fc300627..8ae687d1 100644 --- a/lib/actions/push.ts +++ b/lib/actions/push.ts @@ -368,33 +368,32 @@ export const push: CommandDefinition< const app = appOrDevice; await checkLoggedIn(); - await Bluebird.join( + const [token, baseUrl, owner] = await Promise.all([ sdk.auth.getToken(), sdk.settings.get('balenaUrl'), getAppOwner(sdk, app), - async (token, baseUrl, owner) => { - const opts = { - dockerfilePath, - emulated: options.emulated || false, - multiDockerignore: options['multi-dockerignore'] || false, - nocache: options.nocache || false, - registrySecrets, - headless: options.detached || false, - convertEol, - }; - const args = { - app, - owner, - source, - auth: token, - baseUrl, - nogitignore, - sdk, - opts, - }; - return await remote.startRemoteBuild(args); - }, - ); + ]); + + const opts = { + dockerfilePath, + emulated: options.emulated || false, + multiDockerignore: options['multi-dockerignore'] || false, + nocache: options.nocache || false, + registrySecrets, + headless: options.detached || false, + convertEol, + }; + const args = { + app, + owner, + source, + auth: token, + baseUrl, + nogitignore, + sdk, + opts, + }; + await remote.startRemoteBuild(args); break; case BuildTarget.Device: const device = appOrDevice; diff --git a/lib/actions/tunnel.ts b/lib/actions/tunnel.ts index 74898c8b..11aff425 100644 --- a/lib/actions/tunnel.ts +++ b/lib/actions/tunnel.ts @@ -13,7 +13,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import * as Bluebird from 'bluebird'; import type { CommandDefinition } from 'capitano'; import * as _ from 'lodash'; import { createServer, Server, Socket } from 'net'; @@ -196,7 +195,7 @@ export const tunnel: CommandDefinition = { ) .then( (server) => - new Bluebird.Promise((resolve, reject) => { + new Promise((resolve, reject) => { server.on('error', reject); server.listen(localPort, localAddress, () => { resolve(server); diff --git a/lib/auth/index.ts b/lib/auth/index.ts index d9435567..2df0e2d6 100644 --- a/lib/auth/index.ts +++ b/lib/auth/index.ts @@ -64,5 +64,7 @@ export const login = async () => { }, 1000); const balena = getBalenaSdk(); - return awaitForToken(options).tap(balena.auth.loginWithToken); + const token = await awaitForToken(options); + await balena.auth.loginWithToken(token); + return token; }; diff --git a/lib/auth/server.ts b/lib/auth/server.ts index 33f8e36a..68116729 100644 --- a/lib/auth/server.ts +++ b/lib/auth/server.ts @@ -14,7 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -import * as Bluebird from 'bluebird'; import * as bodyParser from 'body-parser'; import * as express from 'express'; import type { Socket } from 'net'; @@ -79,10 +78,10 @@ export function shutdownServer() { export const awaitForToken = (options: { path: string; port: number; -}): Bluebird => { +}): Promise => { const { app, server } = createServer({ port: options.port }); - return new Bluebird((resolve, reject) => { + return new Promise((resolve, reject) => { app.post(options.path, async (request, response) => { server.close(); // stop listening for new connections try { diff --git a/lib/utils/compose.js b/lib/utils/compose.js index 689d43ee..3ea262e4 100644 --- a/lib/utils/compose.js +++ b/lib/utils/compose.js @@ -269,11 +269,8 @@ function originalTarDirectory(dir, param) { .filter(ignore.filter) .map(function (file) { const relPath = path.relative(path.resolve(dir), file); - return Bluebird.join( - relPath, - fs.stat(file), - readFile(file), - (filename, stats, data) => + return Promise.all([relPath, fs.stat(file), readFile(file)]).then( + ([filename, stats, data]) => pack.entry( { name: toPosixPath(filename), @@ -367,13 +364,15 @@ export function buildProject( } logger.logInfo('Emulation is enabled'); // Copy qemu into all build contexts - return Bluebird.map(imageDescriptors, function (d) { - if (typeof d.image === 'string' || d.image.context == null) { - return; - } - // external image - return qemu.copyQemu(path.join(projectPath, d.image.context), arch); - }); + return Promise.all( + imageDescriptors.map(function (d) { + if (typeof d.image === 'string' || d.image.context == null) { + return; + } + // external image + return qemu.copyQemu(path.join(projectPath, d.image.context), arch); + }), + ); }) .then(( needsQemu, // Tar up the directory, ready for the build stream @@ -488,57 +487,64 @@ export function buildProject( }) .then(function (tasks) { logger.logDebug('Prepared tasks; building...'); - return Bluebird.map( - builder.performBuilds(tasks, docker, BALENA_ENGINE_TMP_PATH), - function (builtImage) { - if (!builtImage.successful) { - /** @type {Error & {serviceName?: string}} */ - const error = builtImage.error ?? new Error(); - error.serviceName = builtImage.serviceName; - throw error; - } + return builder + .performBuilds(tasks, docker, BALENA_ENGINE_TMP_PATH) + .then(function (builtImages) { + return Promise.all( + builtImages.map(function (builtImage) { + if (!builtImage.successful) { + /** @type {Error & {serviceName?: string}} */ + const error = builtImage.error ?? new Error(); + error.serviceName = builtImage.serviceName; + throw error; + } - const d = imageDescriptorsByServiceName[builtImage.serviceName]; - const task = _.find(tasks, { serviceName: builtImage.serviceName }); + const d = imageDescriptorsByServiceName[builtImage.serviceName]; + const task = _.find(tasks, { + serviceName: builtImage.serviceName, + }); - const image = { - serviceName: d.serviceName, - name: typeof d.image === 'string' ? d.image : d.image.tag, - logs: truncateString(task.logBuffer.join('\n'), LOG_LENGTH_MAX), - props: { - dockerfile: builtImage.dockerfile, - projectType: builtImage.projectType, - }, - }; + const image = { + serviceName: d.serviceName, + name: typeof d.image === 'string' ? d.image : d.image.tag, + logs: truncateString(task.logBuffer.join('\n'), LOG_LENGTH_MAX), + props: { + dockerfile: builtImage.dockerfile, + projectType: builtImage.projectType, + }, + }; - // Times here are timestamps, so test whether they're null - // before creating a date out of them, as `new Date(null)` - // creates a date representing UNIX time 0. - if (builtImage.startTime) { - image.props.startTime = new Date(builtImage.startTime); - } - if (builtImage.endTime) { - image.props.endTime = new Date(builtImage.endTime); - } - return docker - .getImage(image.name) - .inspect() - .get('Size') - .then((size) => { - image.props.size = size; - }) - .return(image); - }, - ).tap(function (images) { - const summary = _(images) - .map(({ serviceName, props }) => [ - serviceName, - `Image size: ${humanize.filesize(props.size)}`, - ]) - .fromPairs() - .value(); - renderer.end(summary); - }); + // Times here are timestamps, so test whether they're null + // before creating a date out of them, as `new Date(null)` + // creates a date representing UNIX time 0. + if (builtImage.startTime) { + image.props.startTime = new Date(builtImage.startTime); + } + if (builtImage.endTime) { + image.props.endTime = new Date(builtImage.endTime); + } + return docker + .getImage(image.name) + .inspect() + .get('Size') + .then((size) => { + image.props.size = size; + }) + .return(image); + }), + ); + }) + .then(function (images) { + const summary = _(images) + .map(({ serviceName, props }) => [ + serviceName, + `Image size: ${humanize.filesize(props.size)}`, + ]) + .fromPairs() + .value(); + renderer.end(summary); + return images; + }); }) .finally(renderer.end); } @@ -598,32 +604,34 @@ export const createRelease = function ( * @param {import('docker-toolbelt')} docker * @param {Array} images * @param {Partial} serviceImages - * @returns {Bluebird>} + * @returns {Promise>} */ export const tagServiceImages = (docker, images, serviceImages) => - Bluebird.map(images, function (d) { - const serviceImage = serviceImages[d.serviceName]; - const imageName = serviceImage.is_stored_at__image_location; - const match = /(.*?)\/(.*?)(?::([^/]*))?$/.exec(imageName); - if (match == null) { - throw new Error(`Could not parse imageName: '${imageName}'`); - } - const [, registry, repo, tag = 'latest'] = match; - const name = `${registry}/${repo}`; - return docker - .getImage(d.name) - .tag({ repo: name, tag, force: true }) - .then(() => docker.getImage(`${name}:${tag}`)) - .then((localImage) => ({ - serviceName: d.serviceName, - serviceImage, - localImage, - registry, - repo, - logs: d.logs, - props: d.props, - })); - }); + Promise.all( + images.map(function (d) { + const serviceImage = serviceImages[d.serviceName]; + const imageName = serviceImage.is_stored_at__image_location; + const match = /(.*?)\/(.*?)(?::([^/]*))?$/.exec(imageName); + if (match == null) { + throw new Error(`Could not parse imageName: '${imageName}'`); + } + const [, registry, repo, tag = 'latest'] = match; + const name = `${registry}/${repo}`; + return docker + .getImage(d.name) + .tag({ repo: name, tag, force: true }) + .then(() => docker.getImage(`${name}:${tag}`)) + .then((localImage) => ({ + serviceName: d.serviceName, + serviceImage, + localImage, + registry, + repo, + logs: d.logs, + props: d.props, + })); + }), + ); /** * @param {*} sdk @@ -655,15 +663,19 @@ export const getPreviousRepos = (sdk, docker, logger, appID) => // grab all images from the latest release, return all image locations in the registry if (release.length > 0) { const images = release[0].contains__image; - return Bluebird.map(images, function (d) { - const imageName = d.image[0].is_stored_at__image_location; - return docker.getRegistryAndName(imageName).then(function (registry) { - logger.logDebug( - `Requesting access to previously pushed image repo (${registry.imageName})`, - ); - return registry.imageName; - }); - }); + return Promise.all( + images.map(function (d) { + const imageName = d.image[0].is_stored_at__image_location; + return docker + .getRegistryAndName(imageName) + .then(function (registry) { + logger.logDebug( + `Requesting access to previously pushed image repo (${registry.imageName})`, + ); + return registry.imageName; + }); + }), + ); } else { return []; } @@ -733,41 +745,46 @@ export const pushAndUpdateServiceImages = function ( const reporters = progress.aggregateProgress(images.length, renderer); return Bluebird.using(tty.cursorHidden(), () => - Bluebird.map(images, ({ serviceImage, localImage, props, logs }, index) => - Bluebird.join( - // @ts-ignore - localImage.inspect().get('Size'), - retry( + Promise.all( + images.map(({ serviceImage, localImage, props, logs }, index) => + Promise.all([ // @ts-ignore - () => progress.push(localImage.name, reporters[index], opts), - 3, // `times` - retry 3 times - // @ts-ignore - localImage.name, // `label` included in retry log messages - 2000, // `delayMs` - wait 2 seconds before the 1st retry - 1.4, // `backoffScaler` - wait multiplier for each retry - ).finally(renderer.end), - /** @type {(size: number, digest: string) => void} */ - function (size, digest) { - serviceImage.image_size = size; - serviceImage.content_hash = digest; - serviceImage.build_log = logs; - serviceImage.dockerfile = props.dockerfile; - serviceImage.project_type = props.projectType; - if (props.startTime) { - serviceImage.start_timestamp = props.startTime; - } - if (props.endTime) { - serviceImage.end_timestamp = props.endTime; - } - serviceImage.push_timestamp = new Date(); - serviceImage.status = 'success'; - }, - ) - .tapCatch(function (e) { - serviceImage.error_message = '' + e; - serviceImage.status = 'failed'; - }) - .finally(() => afterEach?.(serviceImage, props)), + localImage.inspect().get('Size'), + retry( + // @ts-ignore + () => progress.push(localImage.name, reporters[index], opts), + 3, // `times` - retry 3 times + // @ts-ignore + localImage.name, // `label` included in retry log messages + 2000, // `delayMs` - wait 2 seconds before the 1st retry + 1.4, // `backoffScaler` - wait multiplier for each retry + ).finally(renderer.end), + ]) + .then( + /** @type {([number, string]) => void} */ + function ([size, digest]) { + serviceImage.image_size = size; + serviceImage.content_hash = digest; + serviceImage.build_log = logs; + serviceImage.dockerfile = props.dockerfile; + serviceImage.project_type = props.projectType; + if (props.startTime) { + serviceImage.start_timestamp = props.startTime; + } + if (props.endTime) { + serviceImage.end_timestamp = props.endTime; + } + serviceImage.push_timestamp = new Date(); + serviceImage.status = 'success'; + }, + ) + .catch(function (e) { + serviceImage.error_message = '' + e; + serviceImage.status = 'failed'; + throw e; + }) + .finally(() => afterEach?.(serviceImage, props)), + ), ), ); }; diff --git a/lib/utils/compose_ts.ts b/lib/utils/compose_ts.ts index 41fd7419..6e259463 100644 --- a/lib/utils/compose_ts.ts +++ b/lib/utils/compose_ts.ts @@ -843,7 +843,9 @@ export async function deployProject( throw err; } finally { logger.logDebug('Untagging images...'); - await Bluebird.map(taggedImages, ({ localImage }) => localImage.remove()); + await Promise.all( + taggedImages.map(({ localImage }) => localImage.remove()), + ); } } finally { runloop = runSpinner(tty, spinner, `${prefix}Saving release...`); diff --git a/lib/utils/deploy-legacy.js b/lib/utils/deploy-legacy.js index 81580afe..20b39805 100644 --- a/lib/utils/deploy-legacy.js +++ b/lib/utils/deploy-legacy.js @@ -36,13 +36,12 @@ const bufferImage = function (docker, imageId, bufferFile) { const image = docker.getImage(imageId); const imageMetadata = image.inspect(); - return Bluebird.join( - image.get(), - imageMetadata.get('Size'), - (imageStream, imageSize) => - streamUtils.buffer(imageStream, bufferFile).tap((bufferedStream) => { + return Promise.all([image.get(), imageMetadata.get('Size')]).then( + ([imageStream, imageSize]) => + streamUtils.buffer(imageStream, bufferFile).then((bufferedStream) => { // @ts-ignore adding an extra property bufferedStream.length = imageSize; + return bufferedStream; }), ); }; @@ -55,7 +54,7 @@ const showPushProgress = function (message) { }; const uploadToPromise = (uploadRequest, logger) => - new Bluebird(function (resolve, reject) { + new Promise(function (resolve, reject) { const handleMessage = function (data) { let obj; data = data.toString(); @@ -88,7 +87,7 @@ const uploadToPromise = (uploadRequest, logger) => }); /** - * @returns {Bluebird<{ buildId: number }>} + * @returns {Promise<{ buildId: number }>} */ const uploadImage = function ( imageStream, diff --git a/lib/utils/device/api.ts b/lib/utils/device/api.ts index d95feace..5189eea9 100644 --- a/lib/utils/device/api.ts +++ b/lib/utils/device/api.ts @@ -194,11 +194,11 @@ export class DeviceAPI { }); } - public getLogStream(): Bluebird { + public getLogStream(): Promise { const url = this.getUrlForAction('logs'); // Don't use the promisified version here as we want to stream the output - return new Bluebird((resolve, reject) => { + return new Promise((resolve, reject) => { const req = request.get(url); req.on('error', reject).on('response', async (res) => { diff --git a/lib/utils/device/deploy.ts b/lib/utils/device/deploy.ts index b883af5a..bb47fe3b 100644 --- a/lib/utils/device/deploy.ts +++ b/lib/utils/device/deploy.ts @@ -361,20 +361,24 @@ export async function performBuilds( // Now tag any external images with the correct name that they should be, // as this won't be done by resin-multibuild - await Bluebird.map(localImages, async (localImage) => { - if (localImage.external) { - // We can be sure that localImage.name is set here, because of the failure code above - const image = docker.getImage(localImage.name!); - await image.tag({ - repo: generateImageName(localImage.serviceName), - force: true, - }); - imagesToRemove.push(localImage.name!); - } - }); + await Promise.all( + localImages.map(async (localImage) => { + if (localImage.external) { + // We can be sure that localImage.name is set here, because of the failure code above + const image = docker.getImage(localImage.name!); + await image.tag({ + repo: generateImageName(localImage.serviceName), + force: true, + }); + imagesToRemove.push(localImage.name!); + } + }), + ); - await Bluebird.map(_.uniq(imagesToRemove), (image) => - docker.getImage(image).remove({ force: true }), + await Promise.all( + _.uniq(imagesToRemove).map((image) => + docker.getImage(image).remove({ force: true }), + ), ); return buildTasks; @@ -512,26 +516,28 @@ async function assignDockerBuildOpts( globalLogger.logDebug(`Using ${images.length} on-device images for cache...`); - await Bluebird.map(buildTasks, async (task: BuildTask) => { - task.dockerOpts = { - cachefrom: images, - labels: { - 'io.resin.local.image': '1', - 'io.resin.local.service': task.serviceName, - }, - t: generateImageName(task.serviceName), - nocache: opts.nocache, - forcerm: true, - }; - if (task.external) { - task.dockerOpts.authconfig = await getAuthConfigObj( - task.imageName!, - opts.registrySecrets, - ); - } else { - task.dockerOpts.registryconfig = opts.registrySecrets; - } - }); + await Promise.all( + buildTasks.map(async (task: BuildTask) => { + task.dockerOpts = { + cachefrom: images, + labels: { + 'io.resin.local.image': '1', + 'io.resin.local.service': task.serviceName, + }, + t: generateImageName(task.serviceName), + nocache: opts.nocache, + forcerm: true, + }; + if (task.external) { + task.dockerOpts.authconfig = await getAuthConfigObj( + task.imageName!, + opts.registrySecrets, + ); + } else { + task.dockerOpts.registryconfig = opts.registrySecrets; + } + }), + ); } function generateImageName(serviceName: string): string { diff --git a/lib/utils/device/logs.ts b/lib/utils/device/logs.ts index 44036470..be8fab4d 100644 --- a/lib/utils/device/logs.ts +++ b/lib/utils/device/logs.ts @@ -1,4 +1,3 @@ -import * as Bluebird from 'bluebird'; import ColorHash = require('color-hash'); import * as _ from 'lodash'; import type { Readable } from 'stream'; @@ -38,8 +37,8 @@ export function displayDeviceLogs( logger: Logger, system: boolean, filterServices?: string[], -): Bluebird { - return new Bluebird((resolve, reject) => { +): Promise { + return new Promise((resolve, reject) => { logs.on('data', (log) => { displayLogLine(log, logger, system, filterServices); }); diff --git a/lib/utils/helpers.ts b/lib/utils/helpers.ts index e75ced0b..35a590fc 100644 --- a/lib/utils/helpers.ts +++ b/lib/utils/helpers.ts @@ -146,22 +146,21 @@ export async function osProgressHandler(step: InitializeEmitter) { export function getAppWithArch( applicationName: string, -): Bluebird { - return Bluebird.join( +): Promise { + return Promise.all([ getApplication(applicationName), getBalenaSdk().models.config.getDeviceTypes(), - function (app, deviceTypes) { - const config = _.find(deviceTypes, { - slug: app.device_type, - }); + ]).then(function ([app, deviceTypes]) { + const config = _.find(deviceTypes, { + slug: app.device_type, + }); - if (!config) { - throw new Error('Could not read application information!'); - } + if (!config) { + throw new Error('Could not read application information!'); + } - return { ...app, arch: config.arch }; - }, - ); + return { ...app, arch: config.arch }; + }); } function getApplication(applicationName: string) { diff --git a/lib/utils/qemu.ts b/lib/utils/qemu.ts index e48b15f1..c3581e92 100644 --- a/lib/utils/qemu.ts +++ b/lib/utils/qemu.ts @@ -44,7 +44,7 @@ export function copyQemu(context: string, arch: string) { .then(() => getQemuPath(arch)) .then( (qemu) => - new Bluebird(function (resolve, reject) { + new Promise(function (resolve, reject) { const read = fs.createReadStream(qemu); const write = fs.createWriteStream(binPath); @@ -83,7 +83,7 @@ export function installQemu(arch: string) { return getQemuPath(arch).then( (qemuPath) => - new Bluebird(function (resolve, reject) { + new Promise(function (resolve, reject) { const installStream = fs.createWriteStream(qemuPath); const qemuArch = balenaArchToQemuArch(arch); diff --git a/lib/utils/remote-build.ts b/lib/utils/remote-build.ts index e7f9731e..9aa08a03 100644 --- a/lib/utils/remote-build.ts +++ b/lib/utils/remote-build.ts @@ -14,7 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ import type { BalenaSDK } from 'balena-sdk'; -import * as Bluebird from 'bluebird'; import * as JSONStream from 'JSONStream'; import * as readline from 'readline'; import * as request from 'request'; @@ -124,7 +123,7 @@ export async function startRemoteBuild(build: RemoteBuild): Promise { } if (!build.opts.headless) { - return new Bluebird((resolve, reject) => { + return new Promise((resolve, reject) => { // Setup interrupt handlers so we can cancel the build if the user presses // ctrl+c diff --git a/lib/utils/ssh.ts b/lib/utils/ssh.ts index b941521d..bb98a390 100644 --- a/lib/utils/ssh.ts +++ b/lib/utils/ssh.ts @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as Bluebird from 'bluebird'; import { spawn, StdioOptions } from 'child_process'; import * as _ from 'lodash'; import { TypedError } from 'typed-error'; @@ -71,7 +70,7 @@ export async function exec( 'inherit', ]; - const exitCode = await new Bluebird((resolve, reject) => { + const exitCode = await new Promise((resolve, reject) => { const ps = spawn(program, args, { stdio }) .on('error', reject) .on('close', resolve); diff --git a/lib/utils/streams.ts b/lib/utils/streams.ts index 0f589208..23f51e88 100644 --- a/lib/utils/streams.ts +++ b/lib/utils/streams.ts @@ -14,20 +14,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import Bluebird = require('bluebird'); import fs = require('fs'); export function buffer( stream: NodeJS.ReadableStream, bufferFile: string, -): Bluebird { +): Promise { const fileWriteStream = fs.createWriteStream(bufferFile); - return new Bluebird(function (resolve, reject) { + return new Promise(function (resolve, reject) { stream.on('error', reject).on('end', resolve).pipe(fileWriteStream); }).then( () => - new Bluebird(function (resolve, reject) { + new Promise(function (resolve, reject) { const fstream = fs.createReadStream(bufferFile); fstream.on('open', () => resolve(fstream)).on('error', reject); diff --git a/lib/utils/tunnel.ts b/lib/utils/tunnel.ts index f9a57b36..088e3387 100644 --- a/lib/utils/tunnel.ts +++ b/lib/utils/tunnel.ts @@ -52,7 +52,7 @@ export const tunnelConnectionToDevice = ( password: token, }; - return (client: Socket): Bluebird => + return (client: Socket): Promise => openPortThroughProxy(vpnUrl, 3128, auth, uuid, port) .then((remote) => { client.pipe(remote); @@ -72,8 +72,9 @@ export const tunnelConnectionToDevice = ( remote.end(); }); }) - .tapCatch(() => { + .catch((e) => { client.end(); + throw e; }); }); }; @@ -95,7 +96,7 @@ const openPortThroughProxy = ( httpHeaders.push(`Proxy-Authorization: Basic ${credentials}`); } - return new Bluebird.Promise((resolve, reject) => { + return new Promise((resolve, reject) => { const proxyTunnel = new Socket(); proxyTunnel.on('error', reject); proxyTunnel.connect(proxyPort, proxyServer, () => {