Merge pull request #3362 from balena-io/112

112
This commit is contained in:
bulldozer-balena[bot] 2020-12-03 15:17:28 +00:00 committed by GitHub
commit b7efa8e1f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 160 additions and 110 deletions

View File

@ -127,12 +127,12 @@ export function FlashResults({
}; };
} & FlexProps) { } & FlexProps) {
const [showErrorsInfo, setShowErrorsInfo] = React.useState(false); const [showErrorsInfo, setShowErrorsInfo] = React.useState(false);
const allFailed = results.devices.successful === 0; const allFailed = !skip && results.devices.successful === 0;
const someFailed = results.devices.failed !== 0 || errors.length !== 0; const someFailed = results.devices.failed !== 0 || errors.length !== 0;
const effectiveSpeed = _.round( const effectiveSpeed = _.round(
bytesToMegabytes( bytesToMegabytes(
results.sourceMetadata.size / results.sourceMetadata.size /
(results.bytesWritten / results.averageFlashingSpeed), (results.sourceMetadata.blockmappedSize / results.averageFlashingSpeed),
), ),
1, 1,
); );
@ -155,7 +155,7 @@ export function FlashResults({
<Txt>{middleEllipsis(image, 24)}</Txt> <Txt>{middleEllipsis(image, 24)}</Txt>
</Flex> </Flex>
<Txt fontSize={24} color="#fff" mb="17px"> <Txt fontSize={24} color="#fff" mb="17px">
Flash Complete! Flash {allFailed ? 'Failed' : 'Complete'}!
</Txt> </Txt>
{skip ? <Txt color="#7e8085">Validation has been skipped</Txt> : null} {skip ? <Txt color="#7e8085">Validation has been skipped</Txt> : null}
</Flex> </Flex>

View File

@ -23,7 +23,7 @@ import { StepButton } from '../../styled-components';
const FlashProgressBar = styled(ProgressBar)` const FlashProgressBar = styled(ProgressBar)`
> div { > div {
width: 220px; width: 100%;
height: 12px; height: 12px;
color: white !important; color: white !important;
text-shadow: none !important; text-shadow: none !important;
@ -33,7 +33,7 @@ const FlashProgressBar = styled(ProgressBar)`
} }
} }
width: 220px; width: 100%;
height: 12px; height: 12px;
margin-bottom: 6px; margin-bottom: 6px;
border-radius: 14px; border-radius: 14px;

View File

@ -17,7 +17,7 @@
import { Drive as DrivelistDrive } from 'drivelist'; import { Drive as DrivelistDrive } from 'drivelist';
import * as electron from 'electron'; import * as electron from 'electron';
import * as sdk from 'etcher-sdk'; import * as sdk from 'etcher-sdk';
import * as _ from 'lodash'; import { Dictionary } from 'lodash';
import * as ipc from 'node-ipc'; import * as ipc from 'node-ipc';
import * as os from 'os'; import * as os from 'os';
import * as path from 'path'; import * as path from 'path';
@ -133,6 +133,14 @@ function writerEnv() {
interface FlashResults { interface FlashResults {
skip?: boolean; skip?: boolean;
cancelled?: boolean; cancelled?: boolean;
results?: {
bytesWritten: number;
devices: {
failed: number;
successful: number;
};
errors: Error[];
};
} }
async function performWrite( async function performWrite(
@ -177,10 +185,12 @@ async function performWrite(
}); });
ipc.server.on('done', (event) => { ipc.server.on('done', (event) => {
event.results.errors = _.map(event.results.errors, (data) => { event.results.errors = event.results.errors.map(
return errors.fromJSON(data); (data: Dictionary<any> & { message: string }) => {
}); return errors.fromJSON(data);
_.merge(flashResults, event); },
);
flashResults.results = event.results;
}); });
ipc.server.on('abort', () => { ipc.server.on('abort', () => {
@ -209,7 +219,7 @@ async function performWrite(
const argv = writerArgv(); const argv = writerArgv();
ipc.server.on('start', async () => { ipc.server.on('start', async () => {
console.log(`Elevating command: ${_.join(argv, ' ')}`); console.log(`Elevating command: ${argv.join(' ')}`);
const env = writerEnv(); const env = writerEnv();
try { try {
const results = await permissions.elevateCommand(argv, { const results = await permissions.elevateCommand(argv, {
@ -231,11 +241,11 @@ async function performWrite(
} }
console.log('Flash results', flashResults); console.log('Flash results', flashResults);
// This likely means the child died halfway through // The flash wasn't cancelled and we didn't get a 'done' event
if ( if (
!flashResults.cancelled && !flashResults.cancelled &&
!flashResults.skip && !flashResults.skip &&
!_.get(flashResults, ['results', 'bytesWritten']) flashResults.results === undefined
) { ) {
reject( reject(
errors.createUserError({ errors.createUserError({

View File

@ -59,6 +59,27 @@ const getErrorMessageFromCode = (errorCode: string) => {
return ''; return '';
}; };
function notifySuccess(
iconPath: string,
basename: string,
drives: any,
devices: { successful: number; failed: number },
) {
notification.send(
'Flash complete!',
messages.info.flashComplete(basename, drives, devices),
iconPath,
);
}
function notifyFailure(iconPath: string, basename: string, drives: any) {
notification.send(
'Oops! Looks like the flash failed.',
messages.error.flashFailure(basename, drives),
iconPath,
);
}
async function flashImageToDrive( async function flashImageToDrive(
isFlashing: boolean, isFlashing: boolean,
goToSuccess: () => void, goToSuccess: () => void,
@ -84,20 +105,20 @@ async function flashImageToDrive(
if (!flashState.wasLastFlashCancelled()) { if (!flashState.wasLastFlashCancelled()) {
const { const {
results = { devices: { successful: 0, failed: 0 } }, results = { devices: { successful: 0, failed: 0 } },
skip,
cancelled,
} = flashState.getFlashResults(); } = flashState.getFlashResults();
notification.send( if (!skip && !cancelled) {
'Flash complete!', if (results.devices.successful > 0) {
messages.info.flashComplete(basename, drives as any, results.devices), notifySuccess(iconPath, basename, drives, results.devices);
iconPath, } else {
); notifyFailure(iconPath, basename, drives);
}
}
goToSuccess(); goToSuccess();
} }
} catch (error) { } catch (error) {
notification.send( notifyFailure(iconPath, basename, drives);
'Oops! Looks like the flash failed.',
messages.error.flashFailure(path.basename(image.path), drives),
iconPath,
);
let errorMessage = getErrorMessageFromCode(error.code); let errorMessage = getErrorMessageFromCode(error.code);
if (!errorMessage) { if (!errorMessage) {
error.image = basename; error.image = basename;
@ -135,6 +156,7 @@ interface FlashStepProps {
failed: number; failed: number;
speed?: number; speed?: number;
eta?: number; eta?: number;
width: string;
} }
export interface DriveWithWarnings extends constraints.DrivelistDrive { export interface DriveWithWarnings extends constraints.DrivelistDrive {
@ -241,6 +263,7 @@ export class FlashStep extends React.PureComponent<
<Flex <Flex
flexDirection="column" flexDirection="column"
alignItems="start" alignItems="start"
width={this.props.width}
style={this.props.style} style={this.props.style}
> >
<FlashSvg <FlashSvg

View File

@ -239,6 +239,7 @@ export class MainPage extends React.Component<
)} )}
<FlashStep <FlashStep
width={this.state.isWebviewShowing ? '220px' : '200px'}
goToSuccess={() => this.setState({ current: 'success' })} goToSuccess={() => this.setState({ current: 'success' })}
shouldFlashStepBeDisabled={shouldFlashStepBeDisabled} shouldFlashStepBeDisabled={shouldFlashStepBeDisabled}
isFlashing={this.state.isFlashing} isFlashing={this.state.isFlashing}

View File

@ -149,7 +149,7 @@ export const Modal = styled(({ style, children, ...props }) => {
})` })`
> div { > div {
padding: 0; padding: 0;
height: 100%; height: 99%;
> div:first-child { > div:first-child {
height: 81%; height: 81%;

View File

@ -100,6 +100,7 @@ export const theme = _.merge({}, Theme, {
font-size: 16px; font-size: 16px;
&& { && {
width: 200px;
height: 48px; height: 48px;
} }

View File

@ -133,7 +133,7 @@ async function createMainWindow() {
width, width,
height, height,
frame: !fullscreen, frame: !fullscreen,
useContentSize: false, useContentSize: true,
show: false, show: false,
resizable: false, resizable: false,
maximizable: false, maximizable: false,

View File

@ -15,12 +15,23 @@
*/ */
import { Drive as DrivelistDrive } from 'drivelist'; import { Drive as DrivelistDrive } from 'drivelist';
import * as sdk from 'etcher-sdk'; import {
BlockDevice,
File,
Http,
Metadata,
SourceDestination,
} from 'etcher-sdk/build/source-destination';
import {
MultiDestinationProgress,
OnProgressFunction,
OnFailFunction,
decompressThenFlash,
} from 'etcher-sdk/build/multi-write';
import { cleanupTmpFiles } from 'etcher-sdk/build/tmp'; import { cleanupTmpFiles } from 'etcher-sdk/build/tmp';
import * as ipc from 'node-ipc'; import * as ipc from 'node-ipc';
import { totalmem } from 'os'; import { totalmem } from 'os';
import { BlockDevice, File, Http } from 'etcher-sdk/build/source-destination';
import { toJSON } from '../../shared/errors'; import { toJSON } from '../../shared/errors';
import { GENERAL_ERROR, SUCCESS } from '../../shared/exit-codes'; import { GENERAL_ERROR, SUCCESS } from '../../shared/exit-codes';
import { delay } from '../../shared/utils'; import { delay } from '../../shared/utils';
@ -85,7 +96,7 @@ export interface WriteResult {
successful: number; successful: number;
}; };
errors: FlashError[]; errors: FlashError[];
sourceMetadata?: sdk.sourceDestination.Metadata; sourceMetadata?: Metadata;
} }
export interface FlashResults extends WriteResult { export interface FlashResults extends WriteResult {
@ -112,19 +123,15 @@ async function writeAndValidate({
onProgress, onProgress,
onFail, onFail,
}: { }: {
source: sdk.sourceDestination.SourceDestination; source: SourceDestination;
destinations: sdk.sourceDestination.BlockDevice[]; destinations: BlockDevice[];
verify: boolean; verify: boolean;
autoBlockmapping: boolean; autoBlockmapping: boolean;
decompressFirst: boolean; decompressFirst: boolean;
onProgress: sdk.multiWrite.OnProgressFunction; onProgress: OnProgressFunction;
onFail: sdk.multiWrite.OnFailFunction; onFail: OnFailFunction;
}): Promise<WriteResult> { }): Promise<WriteResult> {
const { const { sourceMetadata, failures, bytesWritten } = await decompressThenFlash({
sourceMetadata,
failures,
bytesWritten,
} = await sdk.multiWrite.decompressThenFlash({
source, source,
destinations, destinations,
onFail, onFail,
@ -149,7 +156,7 @@ async function writeAndValidate({
}; };
for (const [destination, error] of failures) { for (const [destination, error] of failures) {
const err = error as FlashError; const err = error as FlashError;
const drive = destination as sdk.sourceDestination.BlockDevice; const drive = destination as BlockDevice;
err.device = drive.device; err.device = drive.device;
err.description = drive.description; err.description = drive.description;
result.errors.push(err); result.errors.push(err);
@ -201,7 +208,7 @@ ipc.connectTo(IPC_SERVER_ID, () => {
* @example * @example
* writer.on('progress', onProgress) * writer.on('progress', onProgress)
*/ */
const onProgress = (state: sdk.multiWrite.MultiDestinationProgress) => { const onProgress = (state: MultiDestinationProgress) => {
ipc.of[IPC_SERVER_ID].emit('state', state); ipc.of[IPC_SERVER_ID].emit('state', state);
}; };
@ -237,10 +244,7 @@ ipc.connectTo(IPC_SERVER_ID, () => {
* @example * @example
* writer.on('fail', onFail) * writer.on('fail', onFail)
*/ */
const onFail = ( const onFail = (destination: SourceDestination, error: Error) => {
destination: sdk.sourceDestination.SourceDestination,
error: Error,
) => {
ipc.of[IPC_SERVER_ID].emit('fail', { ipc.of[IPC_SERVER_ID].emit('fail', {
// TODO: device should be destination // TODO: device should be destination
// @ts-ignore (destination.drive is private) // @ts-ignore (destination.drive is private)
@ -257,7 +261,7 @@ ipc.connectTo(IPC_SERVER_ID, () => {
log(`Auto blockmapping: ${options.autoBlockmapping}`); log(`Auto blockmapping: ${options.autoBlockmapping}`);
log(`Decompress first: ${options.decompressFirst}`); log(`Decompress first: ${options.decompressFirst}`);
const dests = options.destinations.map((destination) => { const dests = options.destinations.map((destination) => {
return new sdk.sourceDestination.BlockDevice({ return new BlockDevice({
drive: destination, drive: destination,
unmountOnSuccess: options.unmountOnSuccess, unmountOnSuccess: options.unmountOnSuccess,
write: true, write: true,
@ -298,7 +302,6 @@ ipc.connectTo(IPC_SERVER_ID, () => {
await delay(DISCONNECT_DELAY); await delay(DISCONNECT_DELAY);
await terminate(exitCode); await terminate(exitCode);
} catch (error) { } catch (error) {
log(`Error: ${error.message}`);
exitCode = GENERAL_ERROR; exitCode = GENERAL_ERROR;
ipc.of[IPC_SERVER_ID].emit('error', toJSON(error)); ipc.of[IPC_SERVER_ID].emit('error', toJSON(error));
} }

120
npm-shrinkwrap.json generated
View File

@ -1313,9 +1313,9 @@
} }
}, },
"@balena/apple-plist": { "@balena/apple-plist": {
"version": "0.0.2", "version": "0.0.3",
"resolved": "https://registry.npmjs.org/@balena/apple-plist/-/apple-plist-0.0.2.tgz", "resolved": "https://registry.npmjs.org/@balena/apple-plist/-/apple-plist-0.0.3.tgz",
"integrity": "sha512-pipB4z1nW0YkIN1B5CgcPLzwagkAnmPF5KEuEntE5Pg5F8kNAxmED3LEF1VusAVqdZl6YwtjILzqAmykmRvvIw==", "integrity": "sha512-OCb2lH6twxm0EX4UjMyK9SB8BKqhDA+8NAanThsheALJ2Jys9jsgpnixUakrGaq3qKeNITVoC0NJ4s4Q4bKRfQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"sax": "^1.2.4" "sax": "^1.2.4"
@ -1367,12 +1367,12 @@
"dev": true "dev": true
}, },
"@balena/udif": { "@balena/udif": {
"version": "1.1.0", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/@balena/udif/-/udif-1.1.0.tgz", "resolved": "https://registry.npmjs.org/@balena/udif/-/udif-1.1.1.tgz",
"integrity": "sha512-iZ1GyKVNUcqNQOUem7etcrhzOanRVnuIrNqgcKZiCHunL8aextTdHeEMkY3xEgXpZWTufzDAimVmdrgeUqzT5Q==", "integrity": "sha512-7o+R86ErTbg5RSsmnEDkMPvL8XqNpjg0NwFMmGxUr9f5Ukbmdke+jeJglRfztFE0LFY7RClcjRwbXvZoAbLMEg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@balena/apple-plist": "^0.0.2", "@balena/apple-plist": "0.0.3",
"apple-data-compression": "^0.4.1", "apple-data-compression": "^0.4.1",
"cyclic-32": "^1.1.0", "cyclic-32": "^1.1.0",
"unbzip2-stream": "github:balena-io-modules/unbzip2-stream#4a54f56a25b58950f9e4277c56db2912d62242e7" "unbzip2-stream": "github:balena-io-modules/unbzip2-stream#4a54f56a25b58950f9e4277c56db2912d62242e7"
@ -3274,15 +3274,15 @@
"dev": true "dev": true
}, },
"balena-image-fs": { "balena-image-fs": {
"version": "7.0.4", "version": "7.0.6",
"resolved": "https://registry.npmjs.org/balena-image-fs/-/balena-image-fs-7.0.4.tgz", "resolved": "https://registry.npmjs.org/balena-image-fs/-/balena-image-fs-7.0.6.tgz",
"integrity": "sha512-6jyHqP4nWd2T+XZqAzVVO9Jv+TReNAwODTSBk/k88fGUPmaAy6gHZ2+0+YxzKBQrNr0iFxtkf91UNRv68wehbg==", "integrity": "sha512-LnLVQq9Um1/bmfgOuPRsndCpZIhHVdp7Na3Aq2sX2WUvsUhhXkpEeaer9K9kecWeVEzdqUWJARVXg82Xmke4og==",
"dev": true, "dev": true,
"requires": { "requires": {
"ext2fs": "^3.0.3", "ext2fs": "^3.0.5",
"fatfs": "^0.10.7", "fatfs": "^0.10.7",
"file-disk": "^8.0.0", "file-disk": "^8.0.1",
"partitioninfo": "^6.0.1", "partitioninfo": "^6.0.2",
"typed-error": "^3.2.0" "typed-error": "^3.2.0"
} }
}, },
@ -3418,9 +3418,9 @@
} }
}, },
"blockmap": { "blockmap": {
"version": "4.0.2", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/blockmap/-/blockmap-4.0.2.tgz", "resolved": "https://registry.npmjs.org/blockmap/-/blockmap-4.0.3.tgz",
"integrity": "sha512-jeQSY/yAc/URhOoK/odQtqaIV9wiSB5KKRfERD1pnlkyOciBQwYuZ9Lvt/v8dCdVmn53vNlMKLm4h5Esy+WcnQ==", "integrity": "sha512-FNNohgfxiRKSSwxwbxYoT7qS2g6tTLevlQbLUm72Bzd31yAu+++ZJAV7lwN2MOwtiEC20lNqcsprxqdW5KTZug==",
"dev": true, "dev": true,
"requires": { "requires": {
"debug": "^4.1.1", "debug": "^4.1.1",
@ -5787,9 +5787,9 @@
"dev": true "dev": true
}, },
"drivelist": { "drivelist": {
"version": "9.2.1", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/drivelist/-/drivelist-9.2.1.tgz", "resolved": "https://registry.npmjs.org/drivelist/-/drivelist-9.2.2.tgz",
"integrity": "sha512-oiMDLWUOhoqvVWDvjSrWcz2I42dNuH0Pf1SZlEr86I413n7XoY/YANnqipSynpe86arBW4EbNur7VAl5h8QQ3Q==", "integrity": "sha512-kuigQbvkc9+Y6Rf36d9nv4g4PB19UUPOvxRdQE3JEtggCqdxYCPEsNm6WYOudkfdMIFnHtmbS35QowL/hI/sGQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"bindings": "^1.3.0", "bindings": "^1.3.0",
@ -7357,36 +7357,36 @@
"dev": true "dev": true
}, },
"etcher-sdk": { "etcher-sdk": {
"version": "5.1.5", "version": "5.1.10",
"resolved": "https://registry.npmjs.org/etcher-sdk/-/etcher-sdk-5.1.5.tgz", "resolved": "https://registry.npmjs.org/etcher-sdk/-/etcher-sdk-5.1.10.tgz",
"integrity": "sha512-TXyfxbfJ7Zkw3EWavA3nc7F13EAs8n0BogdZqh0bHhdbQ+vNl1h2+O1F6rrFYqwS01UsXw6YZMXXCOjwYOs04A==", "integrity": "sha512-tCHY6v4txJr6+3KCIYhaLem6U3ZTEiXRtchMZiuZO6X9t2w8U5ntn6RgHbs7YIixrr/17o1aRUnqPKsXrLbDHQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@balena/udif": "^1.1.0", "@balena/udif": "^1.1.1",
"@ronomon/direct-io": "^3.0.1", "@ronomon/direct-io": "^3.0.1",
"aws4-axios": "^1.12.0", "aws4-axios": "^1.12.0",
"axios": "^0.19.2", "axios": "^0.19.2",
"balena-image-fs": "^7.0.4", "balena-image-fs": "^7.0.6",
"blockmap": "^4.0.1", "blockmap": "^4.0.3",
"check-disk-space": "^2.1.0", "check-disk-space": "^2.1.0",
"cyclic-32": "^1.1.0", "cyclic-32": "^1.1.0",
"debug": "^3.1.0", "debug": "^3.1.0",
"drivelist": "^9.2.1", "drivelist": "^9.2.2",
"file-disk": "^8.0.0", "file-disk": "^8.0.1",
"file-type": "^8.0.0", "file-type": "^8.0.0",
"gzip-stream": "^1.1.1", "gzip-stream": "^1.1.2",
"lzma-native": "^6.0.0", "lzma-native": "^6.0.0",
"mountutils": "^1.3.18", "mountutils": "^1.3.20",
"node-raspberrypi-usbboot": "^0.2.9", "node-raspberrypi-usbboot": "^0.2.10",
"outdent": "^0.7.0", "outdent": "^0.7.0",
"partitioninfo": "^6.0.1", "partitioninfo": "^6.0.2",
"rwmutex": "^1.0.0", "rwmutex": "^1.0.0",
"tslib": "^2.0.0", "tslib": "^2.0.0",
"unbzip2-stream": "github:balena-io-modules/unbzip2-stream#4a54f56a25b58950f9e4277c56db2912d62242e7", "unbzip2-stream": "github:balena-io-modules/unbzip2-stream#4a54f56a25b58950f9e4277c56db2912d62242e7",
"unzip-stream": "^0.3.0", "unzip-stream": "^0.3.0",
"xxhash": "^0.3.0", "xxhash": "^0.3.0",
"yauzl": "^2.9.2", "yauzl": "^2.9.2",
"zip-part-stream": "^1.0.2" "zip-part-stream": "^1.0.3"
}, },
"dependencies": { "dependencies": {
"debug": { "debug": {
@ -7548,9 +7548,9 @@
} }
}, },
"ext2fs": { "ext2fs": {
"version": "3.0.3", "version": "3.0.5",
"resolved": "https://registry.npmjs.org/ext2fs/-/ext2fs-3.0.3.tgz", "resolved": "https://registry.npmjs.org/ext2fs/-/ext2fs-3.0.5.tgz",
"integrity": "sha512-KW7pKOd0IhEDhLrZkU186zl4uh2QGOJZ474x0+dxwt9uCrUrSqV5V4jBTr4q0IMNkMvHiSrBmx4CHK1Wd5spjQ==", "integrity": "sha512-QHnfxD7C9jjg1HR5vuZ+oe+IPTM3XwY8OAWU2y2TFUhXXOOf6J7P0M9eQFXDaEUYnT2trdYjJaJQUrldMmhfiQ==",
"dev": true "dev": true
}, },
"extend": { "extend": {
@ -7795,9 +7795,9 @@
} }
}, },
"file-disk": { "file-disk": {
"version": "8.0.0", "version": "8.0.1",
"resolved": "https://registry.npmjs.org/file-disk/-/file-disk-8.0.0.tgz", "resolved": "https://registry.npmjs.org/file-disk/-/file-disk-8.0.1.tgz",
"integrity": "sha512-8A6YSCfrlA1ytsHWK22urpcmCgqd3v0qmVg7bdVcGl7nfDvUWbURNM8hB469DWdu/rTYcrxbx6y776fIRcchig==", "integrity": "sha512-oO1bkG2RmZnMqteiAO3Uhffj/f6PJ5WY3fdVJJuI5tDbDgW3MgQvhQsDpijX81TXCbxRAKaNFdEQABTTyjL+og==",
"dev": true, "dev": true,
"requires": { "requires": {
"tslib": "^2.0.0" "tslib": "^2.0.0"
@ -8513,9 +8513,9 @@
"dev": true "dev": true
}, },
"gzip-stream": { "gzip-stream": {
"version": "1.1.1", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/gzip-stream/-/gzip-stream-1.1.1.tgz", "resolved": "https://registry.npmjs.org/gzip-stream/-/gzip-stream-1.1.2.tgz",
"integrity": "sha512-V4FlTwvLpd5ZPcIjUODt/NrP+yhX6pKNzKYahrcSo6WLeLz5Rvlta00DZ3D13YL7QeOC3D7IYPUGKeuN3x9cEg==", "integrity": "sha512-r1nVZJGbHivD0RxzP+aGV4fs08dzh/IN5MCSR0bCa4FEPo7+azLiypR93f47NqzLZt7MSGf2f8vQ1PbfT3oNIg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@balena/node-crc-utils": "^2.0.0", "@balena/node-crc-utils": "^2.0.0",
@ -11208,9 +11208,9 @@
"dev": true "dev": true
}, },
"mountutils": { "mountutils": {
"version": "1.3.19", "version": "1.3.20",
"resolved": "https://registry.npmjs.org/mountutils/-/mountutils-1.3.19.tgz", "resolved": "https://registry.npmjs.org/mountutils/-/mountutils-1.3.20.tgz",
"integrity": "sha512-U2ZA26fg43cGxZHh6nxHPIUvkZWyFVbsO/5QDFpjgZHhZRk4oD4jJlKuo/X42fSyMvJ2+3jKRKPmBh/cxZ0WQw==", "integrity": "sha512-T61cRGb6xDs8yBvzzI+DiYMEUuWVaVw9hZABiTHy4gxfaFJsg8OwgaLMzmH2/SCcxsEUNGO1ACx7Cq7TJ3AcEA==",
"dev": true, "dev": true,
"requires": { "requires": {
"bindings": "^1.3.0", "bindings": "^1.3.0",
@ -11734,9 +11734,9 @@
} }
}, },
"node-raspberrypi-usbboot": { "node-raspberrypi-usbboot": {
"version": "0.2.9", "version": "0.2.10",
"resolved": "https://registry.npmjs.org/node-raspberrypi-usbboot/-/node-raspberrypi-usbboot-0.2.9.tgz", "resolved": "https://registry.npmjs.org/node-raspberrypi-usbboot/-/node-raspberrypi-usbboot-0.2.10.tgz",
"integrity": "sha512-2HJbtb+yfmKjzVTCAfoIg0/Ur3kAqVNdQGx0U/hnOcgpZ22SXzSmsvr69NgRa4QqdCboXPfKS8mJgefBtXYNbg==", "integrity": "sha512-wLl6DMv707iQdxNFVjj09y7+Opgpiazuoil3ljY6c91ci15GXFpuajBGoZIseJPqoWu3uYbvmODO9slma6bVJQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@balena.io/usb": "^1.3.12", "@balena.io/usb": "^1.3.12",
@ -12445,12 +12445,12 @@
"dev": true "dev": true
}, },
"partitioninfo": { "partitioninfo": {
"version": "6.0.1", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/partitioninfo/-/partitioninfo-6.0.1.tgz", "resolved": "https://registry.npmjs.org/partitioninfo/-/partitioninfo-6.0.2.tgz",
"integrity": "sha512-hmLiVz5G6GPzd1TsAuHTHDoSrKqb7cNr2zhJ+fwMhCg2pRoz7vftaP9kL47pMwusO0jWUwkw62oKfHfv0Wa5+A==", "integrity": "sha512-LxmwiC0tSqlTvjL7SYH0MQYRwQkUTfcm55mZPG8+jPNmhhYfhr7QiYr6FUAaF3ixHlhF5pV/YcSLgp8DXq+jYQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"file-disk": "^8.0.0", "file-disk": "^8.0.1",
"gpt": "^2.0.4", "gpt": "^2.0.4",
"mbr": "^1.1.3", "mbr": "^1.1.3",
"tslib": "^2.0.0", "tslib": "^2.0.0",
@ -14950,8 +14950,8 @@
} }
}, },
"sudo-prompt": { "sudo-prompt": {
"version": "github:zvin/sudo-prompt#81cab70c1f3f816b71539c4c5d7ecf1309094f8c", "version": "github:zvin/sudo-prompt#7cdede2f0da28fbcc2db48402d7d935f3a825c91",
"from": "github:zvin/sudo-prompt#workaround-windows-amperstand-in-username", "from": "github:zvin/sudo-prompt#7cdede2f0da28fbcc2db48402d7d935f3a825c91",
"dev": true "dev": true
}, },
"sumchecker": { "sumchecker": {
@ -15006,9 +15006,9 @@
"dev": true "dev": true
}, },
"sys-class-rgb-led": { "sys-class-rgb-led": {
"version": "2.1.0", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/sys-class-rgb-led/-/sys-class-rgb-led-2.1.0.tgz", "resolved": "https://registry.npmjs.org/sys-class-rgb-led/-/sys-class-rgb-led-2.1.1.tgz",
"integrity": "sha512-ckjrMCWWwg1J4d+B3xlTPLhgK6U/2qpW1TYzCLBSULKoLk2tFchis7nDEOmcbiLfpR/8GQK1Q2CrDNleF0USHA==", "integrity": "sha512-CPx01dR22xsqqgpGQ0BcKWf1hCJNTK/Y/gK/hvNEZX5PyuvUzrCYsBWgletzlaruc47RYGi/0be+ZbkIIiQjnA==",
"dev": true "dev": true
}, },
"tapable": { "tapable": {
@ -17468,9 +17468,9 @@
"dev": true "dev": true
}, },
"zip-part-stream": { "zip-part-stream": {
"version": "1.0.2", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/zip-part-stream/-/zip-part-stream-1.0.2.tgz", "resolved": "https://registry.npmjs.org/zip-part-stream/-/zip-part-stream-1.0.3.tgz",
"integrity": "sha512-2dxIug2ydhnpv1YGRuU7muTpxx4+hoLaQoVwfysaRzWF1GV2s5BDqlTuiQQda/vdfMtKYIamSJffps+0n4QJsw==", "integrity": "sha512-JJm6HvhvUCk7CHusOgRMvqYtMDVGj6HOQdTGxEs+ckWPysGScdZW3Y95pNZFeLZEgqbSTiDmaurLIH8osqdZiQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@balena/node-crc-utils": "^2.0.0", "@balena/node-crc-utils": "^2.0.0",
@ -17509,4 +17509,4 @@
"dev": true "dev": true
} }
} }
} }

View File

@ -77,7 +77,7 @@
"electron-notarize": "^1.0.0", "electron-notarize": "^1.0.0",
"electron-rebuild": "^2.3.2", "electron-rebuild": "^2.3.2",
"electron-updater": "^4.3.5", "electron-updater": "^4.3.5",
"etcher-sdk": "^5.1.5", "etcher-sdk": "^5.1.10",
"file-loader": "^6.0.0", "file-loader": "^6.0.0",
"husky": "^4.2.5", "husky": "^4.2.5",
"immutable": "^3.8.1", "immutable": "^3.8.1",
@ -102,8 +102,8 @@
"spectron": "^11.0.0", "spectron": "^11.0.0",
"string-replace-loader": "^2.3.0", "string-replace-loader": "^2.3.0",
"styled-components": "^5.1.0", "styled-components": "^5.1.0",
"sudo-prompt": "github:zvin/sudo-prompt#workaround-windows-amperstand-in-username", "sudo-prompt": "github:zvin/sudo-prompt#7cdede2f0da28fbcc2db48402d7d935f3a825c91",
"sys-class-rgb-led": "^2.1.0", "sys-class-rgb-led": "^2.1.1",
"tmp": "^0.2.1", "tmp": "^0.2.1",
"ts-loader": "^8.0.0", "ts-loader": "^8.0.0",
"ts-node": "^9.0.0", "ts-node": "^9.0.0",

View File

@ -8,4 +8,13 @@ sentry:
triggerNotification: triggerNotification:
version: 1.5.81 version: 1.5.81
stagingPercentage: 100 stagingPercentage: 100
upstream:
- repo: etcher-sdk
url: https://github.com/balena-io-modules/etcher-sdk
module: 'etcher-sdk'
- repo: sys-class-rgb-led
url: https://github.com/balena-io-modules/sys-class-rgb-led
module: sys-class-rgb-led
- repo: rendition
url: https://github.com/balena-io-modules/rendition
module: rendition

View File

@ -46,7 +46,10 @@ describe('Spectron', function () {
expect(bounds.height).to.be.above(0); expect(bounds.height).to.be.above(0);
expect(bounds.width).to.be.above(0); expect(bounds.width).to.be.above(0);
expect(await app.browserWindow.isMinimized()).to.be.false; expect(await app.browserWindow.isMinimized()).to.be.false;
expect(await app.browserWindow.isVisible()).to.be.true; expect(
(await app.browserWindow.isVisible()) ||
(await app.browserWindow.isFocused()),
).to.be.true;
}); });
it('should set a proper title', async () => { it('should set a proper title', async () => {