mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-02-06 19:19:56 +00:00
Update @balena/lint to v9.1.3
Update @balena/lint from 8.0.0 to 9.1.3 Change-type: patch
This commit is contained in:
parent
36077cacda
commit
c0e7ae9c91
@ -145,7 +145,7 @@ export async function getCapitanoDoc(): Promise<typeof capitanoDoc> {
|
||||
throw new Error(`Error parsing section title`);
|
||||
}
|
||||
// match[1] has the title, match[2] has the rest
|
||||
return match && match[2];
|
||||
return match?.[2];
|
||||
}),
|
||||
mdParser.getSectionOfTitle('Installation'),
|
||||
mdParser.getSectionOfTitle('Choosing a shell (command prompt/terminal)'),
|
||||
|
@ -3,7 +3,7 @@ import * as semver from 'semver';
|
||||
|
||||
const changeTypes = ['major', 'minor', 'patch'] as const;
|
||||
|
||||
const validateChangeType = (maybeChangeType: string = 'minor') => {
|
||||
const validateChangeType = (maybeChangeType = 'minor') => {
|
||||
maybeChangeType = maybeChangeType.toLowerCase();
|
||||
switch (maybeChangeType) {
|
||||
case 'patch':
|
||||
@ -136,5 +136,4 @@ async function main() {
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
main();
|
||||
void main();
|
||||
|
@ -19,6 +19,7 @@ import { spawn } from 'child_process';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import { diffTrimmedLines } from 'diff';
|
||||
import * as whichMod from 'which';
|
||||
|
||||
export const ROOT = path.join(__dirname, '..');
|
||||
|
||||
@ -101,7 +102,6 @@ export function loadPackageJson() {
|
||||
* @returns The program's full path, e.g. 'C:\WINDOWS\System32\OpenSSH\ssh.EXE'
|
||||
*/
|
||||
export async function which(program: string): Promise<string> {
|
||||
const whichMod = await import('which');
|
||||
let programPath: string;
|
||||
try {
|
||||
programPath = await whichMod(program);
|
||||
@ -132,7 +132,7 @@ export async function whichSpawn(
|
||||
.on('error', reject)
|
||||
.on('close', resolve);
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
reject(err as Error);
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
|
@ -57,7 +57,10 @@ require('ts-node').register({
|
||||
project: path.join(rootDir, 'tsconfig.json'),
|
||||
transpileOnly: true,
|
||||
});
|
||||
require('../src/app').run(undefined, { dir: __dirname, development: true });
|
||||
void require('../src/app').run(undefined, {
|
||||
dir: __dirname,
|
||||
development: true,
|
||||
});
|
||||
|
||||
// Modify package.json oclif paths from build/ -> src/, or vice versa
|
||||
function modifyOclifPaths(revert) {
|
||||
|
@ -5,7 +5,7 @@
|
||||
process.env.UV_THREADPOOL_SIZE = '64';
|
||||
|
||||
// Disable oclif registering ts-node
|
||||
process.env.OCLIF_TS_NODE = 0;
|
||||
process.env.OCLIF_TS_NODE = '0';
|
||||
|
||||
async function run() {
|
||||
// Use fast-boot to cache require lookups, speeding up startup
|
||||
@ -18,4 +18,4 @@ async function run() {
|
||||
await require('../build/app').run(undefined, { dir: __dirname });
|
||||
}
|
||||
|
||||
run();
|
||||
void run();
|
||||
|
32
eslint.config.js
Normal file
32
eslint.config.js
Normal file
@ -0,0 +1,32 @@
|
||||
const { FlatCompat } = require('@eslint/eslintrc');
|
||||
|
||||
const compat = new FlatCompat({
|
||||
baseDirectory: __dirname,
|
||||
});
|
||||
module.exports = [
|
||||
...require('@balena/lint/config/eslint.config'),
|
||||
...compat.config({
|
||||
parserOptions: {
|
||||
project: 'tsconfig.dev.json',
|
||||
},
|
||||
ignorePatterns: ['**/generate-completion.js', '**/bin/**/*'],
|
||||
rules: {
|
||||
ignoreDefinitionFiles: 0,
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/no-shadow': 'off',
|
||||
'@typescript-eslint/no-var-requires': 'off',
|
||||
'@typescript-eslint/no-require-imports': 'off',
|
||||
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
|
||||
'@typescript-eslint/prefer-nullish-coalescing': 'warn',
|
||||
|
||||
'no-restricted-imports': ['error', {
|
||||
paths: ['resin-cli-visuals', 'chalk', 'common-tags', 'resin-cli-form'],
|
||||
}],
|
||||
|
||||
'@typescript-eslint/no-unused-vars': ['error', {
|
||||
argsIgnorePattern: '^_',
|
||||
caughtErrorsIgnorePattern: '^_',
|
||||
}],
|
||||
},
|
||||
}),
|
||||
];
|
2145
npm-shrinkwrap.json
generated
2145
npm-shrinkwrap.json
generated
File diff suppressed because it is too large
Load Diff
@ -111,7 +111,7 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@balena/lint": "^8.0.0",
|
||||
"@balena/lint": "^9.1.3",
|
||||
"@electron/notarize": "^2.0.0",
|
||||
"@types/archiver": "^6.0.2",
|
||||
"@types/bluebird": "^3.5.36",
|
||||
|
@ -50,9 +50,9 @@ export default class RevokeCmd extends Command {
|
||||
return;
|
||||
}
|
||||
await Promise.all(
|
||||
apiKeyIds.map(
|
||||
async (id) => await getBalenaSdk().models.apiKey.revoke(Number(id)),
|
||||
),
|
||||
apiKeyIds.map(async (id) => {
|
||||
await getBalenaSdk().models.apiKey.revoke(Number(id));
|
||||
}),
|
||||
);
|
||||
console.log('Successfully revoked the given API keys');
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ export default class DeviceDetectCmd extends Command {
|
||||
try {
|
||||
await docker.ping();
|
||||
return true;
|
||||
} catch (err) {
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}),
|
||||
|
@ -155,7 +155,7 @@ export default class DeviceInitCmd extends Command {
|
||||
try {
|
||||
logger.logDebug(`Process failed, removing device ${device.uuid}`);
|
||||
await balena.models.device.remove(device.uuid);
|
||||
} catch (e) {
|
||||
} catch {
|
||||
// Ignore removal failures, and throw original error
|
||||
}
|
||||
throw e;
|
||||
|
@ -135,7 +135,7 @@ export default class DeviceLogsCmd extends Command {
|
||||
logger.logDebug('Checking we can access device');
|
||||
try {
|
||||
await deviceApi.ping();
|
||||
} catch (e) {
|
||||
} catch {
|
||||
const { ExpectedError } = await import('../../errors');
|
||||
throw new ExpectedError(
|
||||
`Cannot access device at address ${params.device}. Device may not be in local mode.`,
|
||||
|
@ -76,6 +76,6 @@ export default class DeviceRegisterCmd extends Command {
|
||||
options.deviceType,
|
||||
);
|
||||
|
||||
return result && result.uuid;
|
||||
return result.uuid;
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ export default class DeviceSSHCmd extends Command {
|
||||
SSH server port number (default 22222) if the target is an IP address or .local
|
||||
hostname. Otherwise, port number for the balenaCloud gateway (default 22).`,
|
||||
char: 'p',
|
||||
parse: async (p) => parseAsInteger(p, 'port'),
|
||||
parse: (p) => parseAsInteger(p, 'port'),
|
||||
}),
|
||||
tty: Flags.boolean({
|
||||
default: false,
|
||||
@ -110,13 +110,14 @@ export default class DeviceSSHCmd extends Command {
|
||||
// Local connection
|
||||
if (validateLocalHostnameOrIp(params.fleetOrDevice)) {
|
||||
const { performLocalDeviceSSH } = await import('../../utils/device/ssh');
|
||||
return await performLocalDeviceSSH({
|
||||
await performLocalDeviceSSH({
|
||||
hostname: params.fleetOrDevice,
|
||||
port: options.port || 'local',
|
||||
forceTTY: options.tty,
|
||||
verbose: options.verbose,
|
||||
service: params.service,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Remote connection
|
||||
@ -132,7 +133,7 @@ export default class DeviceSSHCmd extends Command {
|
||||
const useProxy = !!proxyConfig && !options.noproxy;
|
||||
|
||||
// this will be a tunnelled SSH connection...
|
||||
await checkNotUsingOfflineMode();
|
||||
checkNotUsingOfflineMode();
|
||||
await checkLoggedIn();
|
||||
const deviceUuid = await getOnlineTargetDeviceUuid(
|
||||
sdk,
|
||||
|
2
src/commands/env/rename.ts
vendored
2
src/commands/env/rename.ts
vendored
@ -41,7 +41,7 @@ export default class EnvRenameCmd extends Command {
|
||||
id: Args.integer({
|
||||
required: true,
|
||||
description: "variable's numeric database ID",
|
||||
parse: async (input) => parseAsInteger(input, 'id'),
|
||||
parse: (input) => parseAsInteger(input, 'id'),
|
||||
}),
|
||||
value: Args.string({
|
||||
required: true,
|
||||
|
2
src/commands/env/rm.ts
vendored
2
src/commands/env/rm.ts
vendored
@ -46,7 +46,7 @@ export default class EnvRmCmd extends Command {
|
||||
id: Args.integer({
|
||||
required: true,
|
||||
description: "variable's numeric database ID",
|
||||
parse: async (input) => parseAsInteger(input, 'id'),
|
||||
parse: (input) => parseAsInteger(input, 'id'),
|
||||
}),
|
||||
};
|
||||
|
||||
|
@ -252,10 +252,7 @@ export default class LocalConfigureCmd extends Command {
|
||||
`${this.CONNECTIONS_FOLDER}/resin-sample.ignore`,
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
return await writeFileAsync(
|
||||
`${this.CONNECTIONS_FOLDER}/resin-wifi`,
|
||||
contents,
|
||||
);
|
||||
await writeFileAsync(`${this.CONNECTIONS_FOLDER}/resin-wifi`, contents);
|
||||
});
|
||||
} else if (_.includes(files, 'resin-sample')) {
|
||||
// Legacy mode, to be removed later
|
||||
@ -269,13 +266,13 @@ export default class LocalConfigureCmd extends Command {
|
||||
} else {
|
||||
// In case there's no file at all (shouldn't happen normally, but the file might have been removed)
|
||||
await imagefs.interact(target, bootPartition, async (_fs) => {
|
||||
return await promisify(_fs.writeFile)(
|
||||
await promisify(_fs.writeFile)(
|
||||
`${this.CONNECTIONS_FOLDER}/resin-wifi`,
|
||||
this.CONNECTION_FILE,
|
||||
);
|
||||
});
|
||||
}
|
||||
return await this.getConfigurationSchema(bootPartition, connectionFileName);
|
||||
return this.getConfigurationSchema(bootPartition, connectionFileName);
|
||||
}
|
||||
|
||||
async removeHostname(schema: any) {
|
||||
|
@ -132,7 +132,7 @@ export default class LoginCmd extends Command {
|
||||
// We can safely assume this won't be undefined as doLogin will throw if this call fails
|
||||
// We also don't need to worry too much about the amount of calls to whoami
|
||||
// as these are cached by the SDK
|
||||
const whoamiResult = (await balena.auth.whoami()) as WhoamiResult;
|
||||
const whoamiResult = (await balena.auth.whoami())!;
|
||||
|
||||
if (whoamiResult.actorType !== 'user' && !options.hideExperimentalWarning) {
|
||||
console.info(stripIndent`
|
||||
@ -168,7 +168,7 @@ ${messages.reachingOut}`);
|
||||
|
||||
async doLogin(
|
||||
loginOptions: FlagsDef,
|
||||
balenaUrl: string = 'balena-cloud.com',
|
||||
balenaUrl = 'balena-cloud.com',
|
||||
token?: string,
|
||||
): Promise<void> {
|
||||
// Token
|
||||
|
@ -292,7 +292,7 @@ export default class OsConfigureCmd extends Command {
|
||||
|
||||
for (const { name, content } of files) {
|
||||
await imagefs.interact(image, bootPartition, async (_fs) => {
|
||||
return await promisify(_fs.writeFile)(
|
||||
await promisify(_fs.writeFile)(
|
||||
path.join(CONNECTIONS_FOLDER, name),
|
||||
content,
|
||||
);
|
||||
|
@ -109,7 +109,7 @@ https://github.com/balena-io-examples/staged-releases\
|
||||
'additional-space': Flags.integer({
|
||||
description:
|
||||
'expand the image by this amount of bytes instead of automatically estimating the required amount',
|
||||
parse: async (x) => parseAsInteger(x, 'additional-space'),
|
||||
parse: (x) => parseAsInteger(x, 'additional-space'),
|
||||
}),
|
||||
'add-certificate': Flags.string({
|
||||
description: `\
|
||||
@ -126,7 +126,7 @@ Can be repeated to add multiple certificates.\
|
||||
dockerPort: Flags.integer({
|
||||
description:
|
||||
'Docker daemon TCP port number (hint: 2375 for balena devices)',
|
||||
parse: async (p) => parseAsInteger(p, 'dockerPort'),
|
||||
parse: (p) => parseAsInteger(p, 'dockerPort'),
|
||||
}),
|
||||
};
|
||||
|
||||
@ -155,7 +155,7 @@ Can be repeated to add multiple certificates.\
|
||||
------------------------------------------------------------------------------
|
||||
`);
|
||||
}
|
||||
} catch (error) {
|
||||
} catch {
|
||||
throw new ExpectedError(
|
||||
`The provided image path does not exist: ${params.image}`,
|
||||
);
|
||||
@ -192,11 +192,11 @@ Can be repeated to add multiple certificates.\
|
||||
event.name,
|
||||
));
|
||||
if (event.action === 'start') {
|
||||
return spinner.start();
|
||||
} else {
|
||||
console.log();
|
||||
return spinner.stop();
|
||||
spinner.start();
|
||||
return;
|
||||
}
|
||||
console.log();
|
||||
spinner.stop();
|
||||
};
|
||||
|
||||
const commit = this.isCurrentCommit(options.commit || '')
|
||||
|
@ -24,7 +24,7 @@ import { tryAsInteger } from '../../utils/validation';
|
||||
import { jsonInfo } from '../../utils/messages';
|
||||
|
||||
export const commitOrIdArg = Args.custom({
|
||||
parse: async (commitOrId: string) => tryAsInteger(commitOrId),
|
||||
parse: tryAsInteger,
|
||||
});
|
||||
|
||||
type FlagsDef = Interfaces.InferredFlags<typeof ReleaseCmd.flags>;
|
||||
|
@ -34,7 +34,7 @@ export default class SSHKeyCmd extends Command {
|
||||
public static args = {
|
||||
id: Args.integer({
|
||||
description: 'balenaCloud ID for the SSH key',
|
||||
parse: async (x) => parseAsInteger(x, 'id'),
|
||||
parse: (x) => parseAsInteger(x, 'id'),
|
||||
required: true,
|
||||
}),
|
||||
};
|
||||
|
@ -40,7 +40,7 @@ export default class SSHKeyRmCmd extends Command {
|
||||
public static args = {
|
||||
id: Args.integer({
|
||||
description: 'balenaCloud ID for the SSH key',
|
||||
parse: async (x) => parseAsInteger(x, 'id'),
|
||||
parse: (x) => parseAsInteger(x, 'id'),
|
||||
required: true,
|
||||
}),
|
||||
};
|
||||
|
@ -69,10 +69,9 @@ export default class VersionCmd extends Command {
|
||||
const { flags: options } = await this.parse(VersionCmd);
|
||||
const versions: JsonVersions = {
|
||||
'balena-cli': (await import('../../../package.json')).version,
|
||||
'Node.js':
|
||||
process.version && process.version.startsWith('v')
|
||||
? process.version.slice(1)
|
||||
: process.version,
|
||||
'Node.js': process.version.startsWith('v')
|
||||
? process.version.slice(1)
|
||||
: process.version,
|
||||
};
|
||||
if (options.json) {
|
||||
console.log(JSON.stringify(versions, null, 4));
|
||||
|
@ -93,7 +93,7 @@ function interpret(error: Error): string {
|
||||
|
||||
if (hasCode(error)) {
|
||||
const errorCodeHandler = messages[error.code];
|
||||
const message = errorCodeHandler && errorCodeHandler(error);
|
||||
const message = errorCodeHandler?.(error);
|
||||
|
||||
if (message) {
|
||||
return message;
|
||||
@ -229,7 +229,7 @@ async function sentryCaptureException(error: Error) {
|
||||
Sentry.captureException(error);
|
||||
try {
|
||||
await Sentry.close(1000);
|
||||
} catch (e) {
|
||||
} catch {
|
||||
if (process.env.DEBUG) {
|
||||
console.error('[debug] Timeout reporting error to sentry.io');
|
||||
}
|
||||
|
@ -209,12 +209,12 @@ See: https://git.io/JRHUW#deprecation-policy`,
|
||||
return indent(body, 2);
|
||||
}
|
||||
|
||||
protected formatDescription(desc: string = '') {
|
||||
protected formatDescription(desc = '') {
|
||||
const chalk = getChalk();
|
||||
|
||||
desc = desc.split('\n')[0];
|
||||
// Remove any ending .
|
||||
if (desc[desc.length - 1] === '.') {
|
||||
if (desc.endsWith('.')) {
|
||||
desc = desc.substring(0, desc.length - 1);
|
||||
}
|
||||
// Lowercase first letter if second char is lowercase, to preserve e.g. 'SSH ...')
|
||||
|
@ -103,7 +103,7 @@ const hook: Hook<'prerun'> = async function (options) {
|
||||
.offlineCompatible ?? DEFAULT_OFFLINE_COMPATIBLE
|
||||
)
|
||||
) {
|
||||
await checkNotUsingOfflineMode();
|
||||
checkNotUsingOfflineMode();
|
||||
}
|
||||
} catch (error) {
|
||||
this.error(error);
|
||||
|
@ -48,7 +48,7 @@ export async function preparseArgs(argv: string[]): Promise<string[]> {
|
||||
if (
|
||||
cmdSlice.length > 1 &&
|
||||
cmdSlice[0] === 'help' &&
|
||||
cmdSlice[1][0] !== '-'
|
||||
!cmdSlice[1].startsWith('-')
|
||||
) {
|
||||
cmdSlice.shift();
|
||||
cmdSlice.push('--help');
|
||||
|
@ -164,9 +164,8 @@ export async function downloadOSImage(
|
||||
stream.on('progress', (state: any) => {
|
||||
if (state != null) {
|
||||
return bar.update(state);
|
||||
} else {
|
||||
return spinner.start();
|
||||
}
|
||||
spinner.start();
|
||||
});
|
||||
|
||||
stream.on('end', () => {
|
||||
|
@ -386,7 +386,7 @@ export class BuildProgressUI implements Renderer {
|
||||
.map(function (service) {
|
||||
const stream = through.obj(function (event, _enc, cb) {
|
||||
eventHandler(service, event);
|
||||
return cb();
|
||||
cb();
|
||||
});
|
||||
stream.pipe(tty.stream, { end: false });
|
||||
return [service, stream];
|
||||
@ -471,17 +471,20 @@ export class BuildProgressUI implements Renderer {
|
||||
const { status, progress, error } = serviceToDataMap[service] ?? {};
|
||||
if (error) {
|
||||
return `${error}`;
|
||||
} else if (progress) {
|
||||
}
|
||||
|
||||
if (progress) {
|
||||
const bar = renderProgressBar(progress, 20);
|
||||
if (status) {
|
||||
return `${bar} ${status}`;
|
||||
}
|
||||
return `${bar}`;
|
||||
} else if (status) {
|
||||
return `${status}`;
|
||||
} else {
|
||||
return 'Waiting...';
|
||||
return bar;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
return status;
|
||||
}
|
||||
return 'Waiting...';
|
||||
})
|
||||
.map((data, index) => [services[index], data])
|
||||
.fromPairs()
|
||||
@ -552,7 +555,7 @@ export class BuildProgressInline implements Renderer {
|
||||
.map(function (service) {
|
||||
const stream = through.obj(function (event, _enc, cb) {
|
||||
eventHandler(service, event);
|
||||
return cb();
|
||||
cb();
|
||||
});
|
||||
stream.pipe(outStream, { end: false });
|
||||
return [service, stream];
|
||||
@ -606,11 +609,11 @@ export class BuildProgressInline implements Renderer {
|
||||
const { status, error } = event;
|
||||
if (error) {
|
||||
return `${error}`;
|
||||
} else if (status) {
|
||||
return `${status}`;
|
||||
} else {
|
||||
return 'Waiting...';
|
||||
}
|
||||
if (status) {
|
||||
return status;
|
||||
}
|
||||
return 'Waiting...';
|
||||
})();
|
||||
|
||||
const prefix = _.padEnd(getChalk().bold(service), this._prefixWidth);
|
||||
|
@ -966,7 +966,7 @@ export async function makeBuildTasks(
|
||||
deviceInfo: DeviceInfo,
|
||||
logger: Logger,
|
||||
projectName: string,
|
||||
releaseHash: string = 'unavailable',
|
||||
releaseHash = 'unavailable',
|
||||
preprocessHook?: (dockerfile: string) => string,
|
||||
): Promise<MultiBuild.BuildTask[]> {
|
||||
const multiBuild = await import('@balena/compose/dist/multibuild');
|
||||
@ -1492,7 +1492,7 @@ export function createRunLoop(tick: (...args: any[]) => void) {
|
||||
},
|
||||
end() {
|
||||
clearInterval(timerId);
|
||||
return runloop.onEnd();
|
||||
runloop.onEnd();
|
||||
},
|
||||
};
|
||||
return runloop;
|
||||
@ -1549,7 +1549,7 @@ function dropEmptyLinesStream() {
|
||||
if (str.trim()) {
|
||||
this.push(str);
|
||||
}
|
||||
return cb();
|
||||
cb();
|
||||
});
|
||||
}
|
||||
|
||||
@ -1570,7 +1570,7 @@ function buildLogCapture(objectMode: boolean, buffer: string[]) {
|
||||
buffer.push(data);
|
||||
}
|
||||
|
||||
return cb(null, data);
|
||||
cb(null, data);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1585,14 +1585,16 @@ function buildProgressAdapter(inline: boolean) {
|
||||
|
||||
return through({ objectMode: true }, function (str, _enc, cb) {
|
||||
if (str == null) {
|
||||
return cb(null, str);
|
||||
cb(null, str);
|
||||
return;
|
||||
}
|
||||
|
||||
if (inline) {
|
||||
return cb(null, { status: str });
|
||||
cb(null, { status: str });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!/^Successfully tagged /.test(str)) {
|
||||
if (!str.startsWith('Successfully tagged ')) {
|
||||
const match = stepRegex.exec(str);
|
||||
if (match) {
|
||||
step = match[1];
|
||||
@ -1607,7 +1609,7 @@ function buildProgressAdapter(inline: boolean) {
|
||||
}
|
||||
}
|
||||
|
||||
return cb(null, { status: str, progress });
|
||||
cb(null, { status: str, progress });
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ export async function generateApplicationConfig(
|
||||
)) as ImgConfig;
|
||||
|
||||
// merge sshKeys to config, when they have been specified
|
||||
if (options.os && options.os.sshKeys) {
|
||||
if (options.os?.sshKeys) {
|
||||
// Create config.os object if it does not exist
|
||||
config.os = config.os ? config.os : {};
|
||||
config.os.sshKeys = config.os.sshKeys
|
||||
|
@ -86,7 +86,7 @@ const uploadToPromise = (uploadRequest: Request, logger: Logger) =>
|
||||
obj = JSON.parse(data);
|
||||
} catch (e) {
|
||||
logger.logError('Error parsing reply from remote side');
|
||||
reject(e);
|
||||
reject(e as Error);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -232,7 +232,7 @@ export const deployLegacy = async function (
|
||||
username,
|
||||
appName,
|
||||
]);
|
||||
await uploadLogs(...args);
|
||||
uploadLogs(...args);
|
||||
}
|
||||
|
||||
return buildId;
|
||||
|
@ -74,7 +74,7 @@ export class DeviceAPI {
|
||||
public constructor(
|
||||
private logger: Logger,
|
||||
addr: string,
|
||||
port: number = 48484,
|
||||
port = 48484,
|
||||
) {
|
||||
this.deviceAddress = `http://${addr}:${port}/`;
|
||||
}
|
||||
@ -201,7 +201,7 @@ export class DeviceAPI {
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = request.get(url);
|
||||
|
||||
req.on('error', reject).on('response', async (res) => {
|
||||
req.on('error', reject).on('response', (res) => {
|
||||
if (res.statusCode !== 200) {
|
||||
reject(
|
||||
new ApiErrors.DeviceAPIError(
|
||||
@ -213,7 +213,7 @@ export class DeviceAPI {
|
||||
try {
|
||||
res.socket.setKeepAlive(true, 1000);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
reject(error as Error);
|
||||
}
|
||||
resolve(res);
|
||||
});
|
||||
@ -238,7 +238,7 @@ export class DeviceAPI {
|
||||
if (_.isObject(opts) && (opts as ObjectWithUrl).url != null) {
|
||||
// the `as string` shouldn't be necessary, but the type system
|
||||
// is getting a little confused
|
||||
url = (opts as ObjectWithUrl).url as string;
|
||||
url = (opts as ObjectWithUrl).url!;
|
||||
} else if (typeof opts === 'string') {
|
||||
url = opts;
|
||||
}
|
||||
@ -252,21 +252,26 @@ export class DeviceAPI {
|
||||
return await new Promise((resolve, reject) => {
|
||||
return request(opts, (err, response, body) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
reject(err as Error);
|
||||
return;
|
||||
}
|
||||
switch (response.statusCode) {
|
||||
case 200:
|
||||
return resolve(body);
|
||||
case 400:
|
||||
return reject(
|
||||
new ApiErrors.BadRequestDeviceAPIError(body.message),
|
||||
);
|
||||
case 503:
|
||||
return reject(
|
||||
new ApiErrors.ServiceUnavailableAPIError(body.message),
|
||||
);
|
||||
default:
|
||||
return reject(new ApiErrors.DeviceAPIError(body.message));
|
||||
case 200: {
|
||||
resolve(body);
|
||||
return;
|
||||
}
|
||||
case 400: {
|
||||
reject(new ApiErrors.BadRequestDeviceAPIError(body.message));
|
||||
return;
|
||||
}
|
||||
case 503: {
|
||||
reject(new ApiErrors.ServiceUnavailableAPIError(body.message));
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
reject(new ApiErrors.DeviceAPIError(body.message));
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -74,11 +74,11 @@ interface ParsedEnvironment {
|
||||
[serviceName: string]: { [key: string]: string };
|
||||
}
|
||||
|
||||
async function environmentFromInput(
|
||||
function environmentFromInput(
|
||||
envs: string[],
|
||||
serviceNames: string[],
|
||||
logger: Logger,
|
||||
): Promise<ParsedEnvironment> {
|
||||
): ParsedEnvironment {
|
||||
// A normal environment variable regex, with an added part
|
||||
// to find a colon followed servicename at the start
|
||||
const varRegex = /^(?:([^\s:]+):)?([^\s]+?)=(.*)$/;
|
||||
@ -143,7 +143,7 @@ export async function deployToDevice(opts: DeviceDeployOptions): Promise<void> {
|
||||
try {
|
||||
globalLogger.logDebug('Checking we can access device');
|
||||
await api.ping();
|
||||
} catch (e) {
|
||||
} catch {
|
||||
throw new ExpectedError(stripIndent`
|
||||
Could not communicate with device supervisor at address ${opts.deviceHost}:${port}.
|
||||
Device may not have local mode enabled. Check with:
|
||||
@ -191,10 +191,7 @@ export async function deployToDevice(opts: DeviceDeployOptions): Promise<void> {
|
||||
});
|
||||
|
||||
// Attempt to attach to the device's docker daemon
|
||||
const docker = connectToDocker(
|
||||
opts.deviceHost,
|
||||
opts.devicePort != null ? opts.devicePort : 2375,
|
||||
);
|
||||
const docker = connectToDocker(opts.deviceHost, opts.devicePort ?? 2375);
|
||||
|
||||
await checkBuildSecretsRequirements(docker, opts.source);
|
||||
globalLogger.logDebug('Tarring all non-ignored files...');
|
||||
@ -231,7 +228,7 @@ export async function deployToDevice(opts: DeviceDeployOptions): Promise<void> {
|
||||
// Print a newline to clearly separate build time and runtime
|
||||
console.log();
|
||||
|
||||
const envs = await environmentFromInput(
|
||||
const envs = environmentFromInput(
|
||||
opts.env,
|
||||
Object.getOwnPropertyNames(project.composition.services),
|
||||
globalLogger,
|
||||
@ -388,7 +385,7 @@ async function performBuilds(
|
||||
);
|
||||
|
||||
// Check for failures
|
||||
await inspectBuildResults(localImages);
|
||||
inspectBuildResults(localImages);
|
||||
|
||||
const imagesToRemove: string[] = [];
|
||||
|
||||
@ -497,7 +494,7 @@ export async function rebuildSingleTask(
|
||||
}
|
||||
|
||||
await assignDockerBuildOpts(docker, [task], opts);
|
||||
await assignOutputHandlers([task], logger, logHandler);
|
||||
assignOutputHandlers([task], logger, logHandler);
|
||||
|
||||
const [localImage] = await multibuild.performBuilds(
|
||||
[task],
|
||||
@ -568,7 +565,7 @@ async function assignDockerBuildOpts(
|
||||
globalLogger.logDebug(`Using ${images.length} on-device images for cache...`);
|
||||
|
||||
await Promise.all(
|
||||
buildTasks.map(async (task: BuildTask) => {
|
||||
buildTasks.map((task: BuildTask) => {
|
||||
task.dockerOpts = {
|
||||
...(task.dockerOpts || {}),
|
||||
...{
|
||||
@ -666,7 +663,7 @@ export function generateTargetState(
|
||||
return targetState;
|
||||
}
|
||||
|
||||
async function inspectBuildResults(images: LocalImage[]): Promise<void> {
|
||||
function inspectBuildResults(images: LocalImage[]): void {
|
||||
const failures: LocalPushErrors.BuildFailure[] = [];
|
||||
|
||||
_.each(images, (image) => {
|
||||
@ -679,6 +676,6 @@ async function inspectBuildResults(images: LocalImage[]): Promise<void> {
|
||||
});
|
||||
|
||||
if (failures.length > 0) {
|
||||
throw new LocalPushErrors.BuildError(failures).toString();
|
||||
throw new LocalPushErrors.BuildError(failures);
|
||||
}
|
||||
}
|
||||
|
@ -191,8 +191,8 @@ export class LivepushManager {
|
||||
);
|
||||
const eventQueue = this.updateEventsWaiting[$serviceName];
|
||||
eventQueue.push(changedPath);
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
this.getDebouncedEventHandler($serviceName)();
|
||||
|
||||
void this.getDebouncedEventHandler($serviceName)();
|
||||
};
|
||||
|
||||
const monitor = this.setupFilesystemWatcher(
|
||||
@ -252,7 +252,7 @@ export class LivepushManager {
|
||||
try {
|
||||
// sync because chokidar defines a sync interface
|
||||
stats = fs.lstatSync(filePath);
|
||||
} catch (err) {
|
||||
} catch {
|
||||
// OK: the file may have been deleted. See also:
|
||||
// https://github.com/paulmillr/chokidar/blob/3.4.3/lib/fsevents-handler.js#L326-L328
|
||||
// https://github.com/paulmillr/chokidar/blob/3.4.3/lib/nodefs-handler.js#L364
|
||||
@ -267,15 +267,15 @@ export class LivepushManager {
|
||||
return dockerignore.ignores(relPath);
|
||||
},
|
||||
});
|
||||
monitor.on('add', (changedPath: string) =>
|
||||
changedPathHandler(serviceName, changedPath),
|
||||
);
|
||||
monitor.on('change', (changedPath: string) =>
|
||||
changedPathHandler(serviceName, changedPath),
|
||||
);
|
||||
monitor.on('unlink', (changedPath: string) =>
|
||||
changedPathHandler(serviceName, changedPath),
|
||||
);
|
||||
monitor.on('add', (changedPath: string) => {
|
||||
changedPathHandler(serviceName, changedPath);
|
||||
});
|
||||
monitor.on('change', (changedPath: string) => {
|
||||
changedPathHandler(serviceName, changedPath);
|
||||
});
|
||||
monitor.on('unlink', (changedPath: string) => {
|
||||
changedPathHandler(serviceName, changedPath);
|
||||
});
|
||||
return monitor;
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ export const dockerConnectionCliFlags = {
|
||||
description:
|
||||
'Docker daemon TCP port number (hint: 2375 for balena devices)',
|
||||
char: 'p',
|
||||
parse: async (p) => parseAsInteger(p, 'dockerPort'),
|
||||
parse: (p) => parseAsInteger(p, 'dockerPort'),
|
||||
}),
|
||||
ca: Flags.string({
|
||||
description: 'Docker host TLS certificate authority file',
|
||||
@ -169,9 +169,7 @@ export async function isBalenaEngine(docker: dockerode): Promise<boolean> {
|
||||
// version of balenaEngine, but it was at one point (mis)spelt 'balaena':
|
||||
// https://github.com/balena-os/balena-engine/pull/32/files
|
||||
const dockerVersion = (await docker.version()) as BalenaEngineVersion;
|
||||
return !!(
|
||||
dockerVersion.Engine && dockerVersion.Engine.match(/balena|balaena/)
|
||||
);
|
||||
return !!dockerVersion.Engine?.match(/balena|balaena/);
|
||||
}
|
||||
|
||||
export async function getDocker(
|
||||
|
@ -84,7 +84,7 @@ export async function readFileWithEolConversion(
|
||||
}
|
||||
|
||||
// Analyse encoding
|
||||
const encoding = await detectEncoding(fileBuffer);
|
||||
const encoding = detectEncoding(fileBuffer);
|
||||
|
||||
// Skip further processing of non-convertible encodings
|
||||
if (!CONVERTIBLE_ENCODINGS.includes(encoding)) {
|
||||
@ -132,10 +132,10 @@ export async function readFileWithEolConversion(
|
||||
* @param fileBuffer File contents whose encoding should be detected
|
||||
* @param bytesRead Optional "file size" if smaller than the buffer size
|
||||
*/
|
||||
export async function detectEncoding(
|
||||
export function detectEncoding(
|
||||
fileBuffer: Buffer,
|
||||
bytesRead = fileBuffer.length,
|
||||
): Promise<string> {
|
||||
): string {
|
||||
// empty file
|
||||
if (bytesRead === 0) {
|
||||
return '';
|
||||
|
@ -281,8 +281,7 @@ export function isWindowsComExeShell() {
|
||||
// neither bash nor sh (e.g. not MSYS, MSYS2, Cygwin, WSL)
|
||||
process.env.SHELL == null &&
|
||||
// Windows cmd.exe or PowerShell
|
||||
process.env.ComSpec != null &&
|
||||
process.env.ComSpec.endsWith('cmd.exe')
|
||||
process.env.ComSpec?.endsWith('cmd.exe')
|
||||
);
|
||||
}
|
||||
|
||||
@ -366,7 +365,7 @@ export function getProxyConfig(): ProxyConfig | undefined {
|
||||
let url: InstanceType<typeof URL>;
|
||||
try {
|
||||
url = new URL(proxyUrl);
|
||||
} catch (_e) {
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
return {
|
||||
@ -469,7 +468,7 @@ export function pickAndRename<T extends Dictionary<any>>(
|
||||
let renameFrom = f;
|
||||
let renameTo = f;
|
||||
const match = f.match(/(?<from>\S+)\s+=>\s+(?<to>\S+)/);
|
||||
if (match && match.groups) {
|
||||
if (match?.groups) {
|
||||
renameFrom = match.groups.from;
|
||||
renameTo = match.groups.to;
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ export const isImageFresh = async (deviceType: string, version: string) => {
|
||||
*/
|
||||
export const isESR = (version: string) => {
|
||||
const match = version.match(/^v?(\d+)\.\d+\.\d+/);
|
||||
const major = parseInt((match && match[1]) || '', 10);
|
||||
const major = parseInt(match?.[1] || '', 10);
|
||||
return major >= 2018; // note: (NaN >= 2018) is false
|
||||
};
|
||||
|
||||
|
@ -39,7 +39,7 @@ export async function disambiguateReleaseParam(
|
||||
|
||||
// Accepting short hashes of 7,8,9 chars.
|
||||
const possibleUuidHashLength = [7, 8, 9, 32, 40, 62].includes(release.length);
|
||||
const hasLeadingZero = release[0] === '0';
|
||||
const hasLeadingZero = release.startsWith('0');
|
||||
const isOnlyNumerical = /^[0-9]+$/.test(release);
|
||||
|
||||
// Reject non-numerical values with invalid uuid/hash lengths
|
||||
@ -78,14 +78,16 @@ export async function disambiguateReleaseParam(
|
||||
/**
|
||||
* Convert to lowercase if looks like slug
|
||||
*/
|
||||
export async function lowercaseIfSlug(s: string) {
|
||||
return s.includes('/') ? s.toLowerCase() : s;
|
||||
export function lowercaseIfSlug(s: string) {
|
||||
return s.includes('/')
|
||||
? Promise.resolve(s.toLowerCase())
|
||||
: Promise.resolve(s);
|
||||
}
|
||||
|
||||
export function normalizeOsVersion(version: string) {
|
||||
// Note that `version` may also be 'latest', 'recommended', 'default'
|
||||
if (/^v?\d+\.\d+\.\d+/.test(version)) {
|
||||
if (version[0] === 'v') {
|
||||
if (version.startsWith('v')) {
|
||||
version = version.slice(1);
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ export function capitanoizeOclifUsage(
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
export async function getCommandsFromManifest() {
|
||||
export function getCommandsFromManifest() {
|
||||
const manifest = require('../../oclif.manifest.json');
|
||||
|
||||
if (manifest.commands == null) {
|
||||
|
@ -119,7 +119,7 @@ export const checkLoggedInIf = async (doCheck: boolean) => {
|
||||
*
|
||||
* @throws {NotAvailableInOfflineModeError}
|
||||
*/
|
||||
export const checkNotUsingOfflineMode = async () => {
|
||||
export const checkNotUsingOfflineMode = () => {
|
||||
if (process.env.BALENARC_OFFLINE_MODE) {
|
||||
throw new NotAvailableInOfflineModeError(stripIndent`
|
||||
This command requires an internet connection, and cannot be used in offline mode.
|
||||
|
@ -390,13 +390,12 @@ async function createApplication(
|
||||
try {
|
||||
const userInfo = await sdk.auth.getUserInfo();
|
||||
username = userInfo.username;
|
||||
} catch (err) {
|
||||
} catch {
|
||||
throw new sdk.errors.BalenaNotLoggedIn();
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
const applicationName = await new Promise<string>(async (resolve, reject) => {
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
try {
|
||||
const appName = await getCliForm().ask({
|
||||
@ -418,11 +417,13 @@ async function createApplication(
|
||||
'You already have a fleet with that name; please choose another.',
|
||||
);
|
||||
continue;
|
||||
} catch (err) {
|
||||
return resolve(appName);
|
||||
} catch {
|
||||
resolve(appName);
|
||||
return;
|
||||
}
|
||||
} catch (err) {
|
||||
return reject(err);
|
||||
reject(err as Error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -452,9 +453,7 @@ async function generateApplicationConfig(
|
||||
const manifest = await sdk.models.config.getDeviceTypeManifestBySlug(
|
||||
app.is_for__device_type[0].slug,
|
||||
);
|
||||
const opts =
|
||||
manifest.options &&
|
||||
manifest.options.filter((opt) => opt.name !== 'network');
|
||||
const opts = manifest.options?.filter((opt) => opt.name !== 'network');
|
||||
|
||||
const override = {
|
||||
appUpdatePollInterval: options.appUpdatePollInterval,
|
||||
|
@ -114,7 +114,7 @@ async function installQemu(arch: string, qemuPath: string) {
|
||||
stream.resume();
|
||||
}
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
reject(err as Error);
|
||||
}
|
||||
});
|
||||
request(qemuUrl)
|
||||
|
@ -246,7 +246,8 @@ function getBuilderMessageHandler(
|
||||
console.error(`[debug] handling message: ${JSON.stringify(obj)}`);
|
||||
}
|
||||
if (obj.type != null && obj.type === 'metadata') {
|
||||
return handleBuilderMetadata(obj, build);
|
||||
handleBuilderMetadata(obj, build);
|
||||
return;
|
||||
}
|
||||
if (obj.message) {
|
||||
readline.clearLine(process.stdout, 0);
|
||||
@ -423,10 +424,20 @@ async function getRemoteBuildStream(
|
||||