From 0339160a0b625a3e05e6dcdd3c4c642599cbab4e Mon Sep 17 00:00:00 2001 From: Otavio Jacobi <otaviojacobi@gmail.com> Date: Wed, 4 Sep 2024 13:53:39 -0300 Subject: [PATCH 1/3] Remove not necessary 'import = require' syntax for js-yaml Change-type: patch --- npm-shrinkwrap.json | 18 +++++++++--------- src/commands/release/index.ts | 4 ++-- src/utils/compose_ts.ts | 9 ++++----- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index b5be4abf..482c693f 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -3894,9 +3894,9 @@ } }, "node_modules/@types/node": { - "version": "20.16.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.3.tgz", - "integrity": "sha512-/wdGiWRkMOm53gAsSyFMXFZHbVg7C6CbkrzHNpaHoYfsUWPg7m6ZRKtvQjgvQ9i8WT540a3ydRlRQbxjY30XxQ==", + "version": "20.16.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.4.tgz", + "integrity": "sha512-ioyQ1zK9aGEomJ45zz8S8IdzElyxhvP1RVWnPrXDf6wFaUb+kk1tEcVVJkF7RPGM0VWI7cp5U57oCPIn5iN1qg==", "dependencies": { "undici-types": "~6.19.2" } @@ -5681,9 +5681,9 @@ } }, "node_modules/balena-sdk/node_modules/@types/node": { - "version": "18.19.48", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.48.tgz", - "integrity": "sha512-7WevbG4ekUcRQSZzOwxWgi5dZmTak7FaxXDoW7xVxPBmKx1rTzfmRLkeCgJzcbBnOV2dkhAPc8cCeT6agocpjg==", + "version": "18.19.49", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.49.tgz", + "integrity": "sha512-ALCeIR6n0nQ7j0FUF1ycOhrp6+XutJWqEu/vtdEqXFUQwkBfgUA5cEg3ZNmjWGF/ZYA/FcF9QMkL55Ar0O6UrA==", "dependencies": { "undici-types": "~5.26.4" } @@ -14324,9 +14324,9 @@ } }, "node_modules/patch-package/node_modules/yaml": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", - "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", "bin": { "yaml": "bin.mjs" }, diff --git a/src/commands/release/index.ts b/src/commands/release/index.ts index a73a8d31..a05d02a6 100644 --- a/src/commands/release/index.ts +++ b/src/commands/release/index.ts @@ -20,7 +20,7 @@ import Command from '../../command'; import * as cf from '../../utils/common-flags'; import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy'; import type * as BalenaSdk from 'balena-sdk'; -import jsyaml = require('js-yaml'); +import * as yaml from 'js-yaml'; import { tryAsInteger } from '../../utils/validation'; import { jsonInfo } from '../../utils/messages'; @@ -82,7 +82,7 @@ export default class ReleaseCmd extends Command { $select: 'composition', }); - console.log(jsyaml.dump(release.composition)); + console.log(yaml.dump(release.composition)); } async showReleaseInfo( diff --git a/src/utils/compose_ts.ts b/src/utils/compose_ts.ts index 8cb9ae5b..c1c130a4 100644 --- a/src/utils/compose_ts.ts +++ b/src/utils/compose_ts.ts @@ -19,7 +19,7 @@ import type { BalenaSDK } from 'balena-sdk'; import type { TransposeOptions } from '@balena/compose/dist/emulate'; import type * as Dockerode from 'dockerode'; import { promises as fs } from 'fs'; -import jsyaml = require('js-yaml'); +import * as yaml from 'js-yaml'; import * as _ from 'lodash'; import * as path from 'path'; import type { @@ -180,7 +180,6 @@ async function mergeDevComposeOverlay( interface ComposeObj { services?: object; } - const yaml = await import('js-yaml'); const loadObj = (inputStr: string): ComposeObj => (yaml.load(inputStr) || {}) as ComposeObj; try { @@ -659,7 +658,7 @@ async function loadBuildMetatada( if (metadataPath.endsWith('json')) { buildMetadata = JSON.parse(rawString); } else { - buildMetadata = require('js-yaml').load(rawString); + buildMetadata = yaml.load(rawString) as MultiBuild.ParsedBalenaYml; } } catch (err) { throw new ExpectedError( @@ -944,7 +943,7 @@ async function parseRegistrySecrets( const multiBuild = await import('@balena/compose/dist/multibuild'); const registrySecrets = new multiBuild.RegistrySecretValidator().validateRegistrySecrets( - isYaml ? require('js-yaml').load(raw) : JSON.parse(raw), + isYaml ? yaml.load(raw) : JSON.parse(raw), ); multiBuild.addCanonicalDockerHubEntry(registrySecrets); return registrySecrets; @@ -1494,7 +1493,7 @@ async function getContractContent( let asJson; try { - asJson = jsyaml.load(fileContentAsString); + asJson = yaml.load(fileContentAsString); } catch (err) { throw new ExpectedError( `Error parsing file "${filePath}":\n ${err.message}`, From 6efd24489ffa10dc616cd0224d4de889b2029709 Mon Sep 17 00:00:00 2001 From: Otavio Jacobi <otaviojacobi@gmail.com> Date: Wed, 4 Sep 2024 14:33:52 -0300 Subject: [PATCH 2/3] Remove the use of CJS require() on test files Change-type: patch --- tests/auth/server.spec.ts | 2 +- tests/auth/utils.spec.ts | 6 +++--- tests/commands/build.spec.ts | 2 +- tests/commands/env/envs.spec.ts | 3 ++- tests/commands/ssh.spec.ts | 2 +- tests/deprecation.spec.ts | 2 +- tests/docker-build.ts | 12 ++++++------ tests/helpers.ts | 5 ++--- tests/nock/builder-mock.ts | 2 +- tests/nock/nock-mock.ts | 3 +-- tests/nock/proxy-server.ts | 3 +-- tests/utils/device/live.spec.ts | 4 ++-- 12 files changed, 22 insertions(+), 24 deletions(-) diff --git a/tests/auth/server.spec.ts b/tests/auth/server.spec.ts index 6a399d1b..2e3245ab 100644 --- a/tests/auth/server.spec.ts +++ b/tests/auth/server.spec.ts @@ -16,7 +16,7 @@ */ import * as chai from 'chai'; -import chaiAsPromised = require('chai-as-promised'); +import * as chaiAsPromised from 'chai-as-promised'; import * as ejs from 'ejs'; import * as fs from 'fs'; import * as path from 'path'; diff --git a/tests/auth/utils.spec.ts b/tests/auth/utils.spec.ts index ad1e8285..7db48171 100644 --- a/tests/auth/utils.spec.ts +++ b/tests/auth/utils.spec.ts @@ -1,15 +1,15 @@ import * as Bluebird from 'bluebird'; import { expect } from 'chai'; -import rewire = require('rewire'); import * as sinon from 'sinon'; import * as url from 'url'; import { getBalenaSdk } from '../../build/utils/lazy'; import tokens from './tokens'; -const utils = rewire('../../build/auth/utils'); const balena = getBalenaSdk(); -describe('Utils:', function () { +describe('Utils:', async function () { + const rewire = await import('rewire'); + const utils = rewire('../../build/auth/utils'); describe('.getDashboardLoginURL()', function () { it('should eventually be a valid url', () => utils diff --git a/tests/commands/build.spec.ts b/tests/commands/build.spec.ts index d402f551..ec5400a0 100644 --- a/tests/commands/build.spec.ts +++ b/tests/commands/build.spec.ts @@ -259,7 +259,7 @@ describe('balena build', function () { const fsModPath = 'fs'; const fsMod = await import(fsModPath); const qemuModPath = '../../build/utils/qemu'; - const qemuMod = require(qemuModPath); + const qemuMod = await import(qemuModPath); const qemuBinPath = await qemuMod.getQemuPath(arch); try { // patch fs.access and fs.stat to pretend that a copy of the Qemu binary diff --git a/tests/commands/env/envs.spec.ts b/tests/commands/env/envs.spec.ts index 5c429299..aec9e816 100644 --- a/tests/commands/env/envs.spec.ts +++ b/tests/commands/env/envs.spec.ts @@ -20,6 +20,7 @@ import { stripIndent } from '../../../build/utils/lazy'; import { BalenaAPIMock } from '../../nock/balena-api-mock'; import { runCommand } from '../../helpers'; +import { randomBytes } from 'node:crypto'; describe('balena envs', function () { const appName = 'test'; @@ -32,7 +33,7 @@ describe('balena envs', function () { api.expectGetWhoAmI({ optional: true, persist: true }); api.expectGetMixpanel({ optional: true }); // Random device UUID used to frustrate _.memoize() in utils/cloud.ts - fullUUID = require('crypto').randomBytes(16).toString('hex'); + fullUUID = randomBytes(16).toString('hex'); shortUUID = fullUUID.substring(0, 7); }); diff --git a/tests/commands/ssh.spec.ts b/tests/commands/ssh.spec.ts index 4e67b7e4..f2d05874 100644 --- a/tests/commands/ssh.spec.ts +++ b/tests/commands/ssh.spec.ts @@ -16,7 +16,7 @@ */ import { expect } from 'chai'; -import mock = require('mock-require'); +import * as mock from 'mock-require'; import type { Server } from 'net'; import { createServer } from 'net'; diff --git a/tests/deprecation.spec.ts b/tests/deprecation.spec.ts index 1e37a42e..f42b128b 100644 --- a/tests/deprecation.spec.ts +++ b/tests/deprecation.spec.ts @@ -18,7 +18,7 @@ import * as settings from 'balena-settings-client'; import { getStorage } from 'balena-settings-storage'; import { expect } from 'chai'; -import mock = require('mock-require'); +import * as mock from 'mock-require'; import * as semver from 'semver'; import * as sinon from 'sinon'; diff --git a/tests/docker-build.ts b/tests/docker-build.ts index 20b912dd..84841a4b 100644 --- a/tests/docker-build.ts +++ b/tests/docker-build.ts @@ -20,12 +20,12 @@ import * as _ from 'lodash'; import { promises as fs } from 'fs'; import * as path from 'path'; import { PathUtils } from '@balena/compose/dist/multibuild'; -import rewire = require('rewire'); import * as sinon from 'sinon'; import { Readable } from 'stream'; import * as tar from 'tar-stream'; import { streamToBuffer } from 'tar-utils'; import { URL } from 'url'; +import { diff } from 'deep-object-diff'; import { makeImageName } from '../build/utils/compose_ts'; import { stripIndent } from '../build/utils/lazy'; @@ -101,8 +101,6 @@ export async function inspectTarStream( try { expect($expected).to.deep.equal(found); } catch (e) { - const { diff } = - require('deep-object-diff') as typeof import('deep-object-diff'); const diffStr = JSON.stringify( diff($expected, found), (_k, v) => (v === undefined ? 'undefined' : v), @@ -202,7 +200,7 @@ export async function testDockerBuildStream(o: { } } - resetDockerignoreCache(); + await resetDockerignoreCache(); const { exitCode, out, err } = await runCommand(o.commandLine); @@ -254,7 +252,7 @@ export async function testPushBuildStream(o: { inspectTarStream(buildRequestBody, o.expectedFiles, o.projectPath), }); - resetDockerignoreCache(); + await resetDockerignoreCache(); const { out, err } = await runCommand(o.commandLine); @@ -262,7 +260,9 @@ export async function testPushBuildStream(o: { expect(cleanOutput(out, true)).to.include.members(expectedResponseLines); } -export function resetDockerignoreCache() { +export async function resetDockerignoreCache() { + const rewire = await import('rewire'); + if (process.env.BALENA_CLI_TEST_TYPE !== 'source') { return; } diff --git a/tests/helpers.ts b/tests/helpers.ts index dddf112e..9da54649 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -19,6 +19,8 @@ import * as _ from 'lodash'; import * as path from 'path'; import * as packageJSON from '../package.json'; +import { getNodeEngineVersionWarn } from '../build/utils/messages'; +import { warnify } from '../build/utils/messages'; const balenaExe = process.platform === 'win32' ? 'balena.exe' : 'balena'; const standalonePath = path.resolve(__dirname, '..', 'build-bin', balenaExe); @@ -41,7 +43,6 @@ function matchesNodeEngineVersionWarn(msg: string) { .map((l) => l.trim()) .filter((l) => l); - const { getNodeEngineVersionWarn } = require('../build/utils/messages'); let nodeEngineWarn: string = getNodeEngineVersionWarn( 'x.y.z', packageJSON.engines.node, @@ -179,8 +180,6 @@ async function runCommandInSubprocess( const msg = ` Error (possibly expected) executing child CLI process "${standalonePath}" ${$error}`; - const { warnify } = - require('../build/utils/messages') as typeof import('../build/utils/messages'); console.error(warnify(msg, '[debug] ')); } resolve(); diff --git a/tests/nock/builder-mock.ts b/tests/nock/builder-mock.ts index ffed6304..b0f69d79 100644 --- a/tests/nock/builder-mock.ts +++ b/tests/nock/builder-mock.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import Bluebird = require('bluebird'); +import * as Bluebird from 'bluebird'; import * as path from 'path'; import * as zlib from 'zlib'; diff --git a/tests/nock/nock-mock.ts b/tests/nock/nock-mock.ts index 04ce0d6d..80cd37b2 100644 --- a/tests/nock/nock-mock.ts +++ b/tests/nock/nock-mock.ts @@ -17,6 +17,7 @@ import * as nock from 'nock'; import * as fs from 'fs'; +import { interceptorServerPort } from './proxy-server'; export interface ScopeOpts { optional?: boolean; @@ -170,8 +171,6 @@ export class NockMock { } protected handleUnexpectedRequest(req: any) { - const { interceptorServerPort } = - require('./proxy-server') as typeof import('./proxy-server'); const o = req.options || {}; const u = o.uri || {}; const method = req.method; diff --git a/tests/nock/proxy-server.ts b/tests/nock/proxy-server.ts index d160e93d..221171d9 100644 --- a/tests/nock/proxy-server.ts +++ b/tests/nock/proxy-server.ts @@ -55,6 +55,7 @@ */ import * as http from 'http'; +import * as httpProxy from 'http-proxy'; const proxyServers: http.Server[] = []; @@ -81,8 +82,6 @@ export async function createProxyServerOnce(): Promise<[number, number]> { } async function createProxyServer(): Promise<[number, number]> { - const httpProxy = require('http-proxy') as typeof import('http-proxy'); - const interceptorPort = await createInterceptorServer(); const proxy = httpProxy.createProxyServer(); diff --git a/tests/utils/device/live.spec.ts b/tests/utils/device/live.spec.ts index 6ca79bb6..510df946 100644 --- a/tests/utils/device/live.spec.ts +++ b/tests/utils/device/live.spec.ts @@ -132,8 +132,8 @@ describeSS('LivepushManager::setupFilesystemWatcher', function () { await setupDockerignoreTestData({ cleanup: true }); }); - this.beforeEach(() => { - resetDockerignoreCache(); + this.beforeEach(async () => { + await resetDockerignoreCache(); }); describe('for project no-docker-compose/basic', function () { From facc66e9f97d075610d4383efa92dceb5b4f7acf Mon Sep 17 00:00:00 2001 From: Otavio Jacobi <otaviojacobi@gmail.com> Date: Wed, 4 Sep 2024 14:47:18 -0300 Subject: [PATCH 3/3] Reduce use of CJS require() on automation files Change-type: patch --- automation/capitanodoc/index.ts | 9 ++++++--- automation/deploy-bin.ts | 22 +++++++++------------- automation/utils.ts | 8 ++++++-- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/automation/capitanodoc/index.ts b/automation/capitanodoc/index.ts index b82f0097..4bb8047a 100644 --- a/automation/capitanodoc/index.ts +++ b/automation/capitanodoc/index.ts @@ -39,7 +39,7 @@ export async function renderMarkdown(): Promise<string> { }; for (const jsFilename of commandCategory.files) { - category.commands.push(...importOclifCommands(jsFilename)); + category.commands.push(...(await importOclifCommands(jsFilename))); } result.categories.push(category); } @@ -78,7 +78,9 @@ class FakeHelpCommand { }; } -function importOclifCommands(jsFilename: string): OclifCommand[] { +async function importOclifCommands( + jsFilename: string, +): Promise<OclifCommand[]> { // TODO: Currently oclif commands with no `usage` overridden will cause // an error when parsed. This should be improved so that `usage` does not have // to be overridden if not necessary. @@ -86,7 +88,8 @@ function importOclifCommands(jsFilename: string): OclifCommand[] { const command: OclifCommand = jsFilename === 'help' ? (new FakeHelpCommand() as unknown as OclifCommand) - : (require(path.join(process.cwd(), jsFilename)).default as OclifCommand); + : ((await import(path.join(process.cwd(), jsFilename))) + .default as OclifCommand); return [command]; } diff --git a/automation/deploy-bin.ts b/automation/deploy-bin.ts index 4a44a7da..4a345822 100644 --- a/automation/deploy-bin.ts +++ b/automation/deploy-bin.ts @@ -17,19 +17,15 @@ import * as _ from 'lodash'; import * as semver from 'semver'; +import { Octokit } from '@octokit/rest'; +import { throttling } from '@octokit/plugin-throttling'; const { GITHUB_TOKEN } = process.env; /** Return a cached Octokit instance, creating a new one as needed. */ const getOctokit = _.once(function () { - const Octokit = ( - require('@octokit/rest') as typeof import('@octokit/rest') - ).Octokit.plugin( - ( - require('@octokit/plugin-throttling') as typeof import('@octokit/plugin-throttling') - ).throttling, - ); - return new Octokit({ + const OctokitConstructor = Octokit.plugin(throttling); + return new OctokitConstructor({ auth: GITHUB_TOKEN, throttle: { onRateLimit: (retryAfter: number, options: any) => { @@ -65,16 +61,16 @@ const getOctokit = _.once(function () { * 'pages' is the total number of pages, and 'ordinal' is the ordinal number * (3rd, 4th, 5th...) of the first item in the current page. */ -function getPageNumbers( +async function getPageNumbers( response: any, perPageDefault: number, -): { page: number; pages: number; ordinal: number } { +): Promise<{ page: number; pages: number; ordinal: number }> { const res = { page: 1, pages: 1, ordinal: 1 }; if (!response.headers.link) { return res; } - const parse = - require('parse-link-header') as typeof import('parse-link-header'); + const parse = await import('parse-link-header'); + const parsed = parse(response.headers.link); if (parsed == null) { throw new Error(`Failed to parse link header: '${response.headers.link}'`); @@ -129,7 +125,7 @@ async function updateGitHubReleaseDescriptions( page: thisPage, pages: totalPages, ordinal, - } = getPageNumbers(response, perPage); + } = await getPageNumbers(response, perPage); let i = 0; for (const cliRelease of response.data) { const prefix = `[#${ordinal + i++} pg ${thisPage}/${totalPages}]`; diff --git a/automation/utils.ts b/automation/utils.ts index 77c97b2b..6c21d76c 100644 --- a/automation/utils.ts +++ b/automation/utils.ts @@ -17,6 +17,8 @@ import { spawn } from 'child_process'; import * as path from 'path'; +import * as fs from 'fs'; +import { diffTrimmedLines } from 'diff'; export const ROOT = path.join(__dirname, '..'); @@ -64,7 +66,6 @@ export class StdOutTap { * https://www.npmjs.com/package/diff */ export function diffLines(str1: string, str2: string): string { - const { diffTrimmedLines } = require('diff'); const diffObjs = diffTrimmedLines(str1, str2); const prefix = (chunk: string, char: string) => chunk @@ -84,7 +85,10 @@ export function diffLines(str1: string, str2: string): string { } export function loadPackageJson() { - return require(path.join(ROOT, 'package.json')); + const packageJsonPath = path.join(ROOT, 'package.json'); + + const packageJson = fs.readFileSync(packageJsonPath, 'utf8'); + return JSON.parse(packageJson); } /**