Compare commits

..

1 Commits

Author SHA1 Message Date
c9b95f19d1 Remove deprecated request library
Change-type: patch
2025-05-28 14:12:13 -03:00
20 changed files with 768 additions and 1527 deletions

View File

@ -18,7 +18,7 @@ inputs:
default: 'accounts+apple@balena.io'
NODE_VERSION:
type: string
default: '22.x'
default: '20.x'
VERBOSE:
type: string
default: 'true'

View File

@ -15,7 +15,7 @@ inputs:
# --- custom environment
NODE_VERSION:
type: string
default: '22.x'
default: '20.x'
VERBOSE:
type: string
default: "true"

View File

@ -1,192 +1,3 @@
- commits:
- subject: "Deploy: Limit the submitted error_message of images that fail to build
to 1000 characters"
hash: bddad252f7cb412a3d417be1d7bd7e4ed9726b8e
body: ""
footer:
Change-type: patch
change-type: patch
See: https://balena.fibery.io/Work/Project/re-pitching-API-Limit-size-of-large-fields-975
see: https://balena.fibery.io/Work/Project/re-pitching-API-Limit-size-of-large-fields-975
author: Thodoris Greasidis
nested: []
version: 22.1.1
title: ""
date: 2025-06-19T09:32:52.976Z
- commits:
- subject: Add support for node 22
hash: f80b8e63b1e5b22dd95b034fe14da0a7e3ab4986
body: ""
footer:
Change-type: minor
change-type: minor
author: Otavio Jacobi
nested: []
- subject: Bump etcher-sdk to v10.0.0
hash: b32514f5afb4fdd12e4a9dca5e2a1d53e727b434
body: |
Update balena-device-init from 8.1.3 to 8.1.1
Update etcher-sdk from 9.1.4 to 10.0.0
Update resin-cli-form from 3.0.0 to 4.0.0
Update resin-cli-visuals from 2.0.1 to 3.0.0
footer:
Change-type: patch
change-type: patch
author: Otavio Jacobi
nested:
- commits:
- subject: Drop support to node18 and add support to node 22 & 24
hash: 95e577823f642a6c0e500aa29fc150b7807d84f7
body: ""
footer:
Change-type: major
change-type: major
author: Otavio Jacobi
nested: []
version: etcher-sdk-10.0.0
title: ""
date: 2025-06-02T09:12:32.868Z
version: 22.1.0
title: ""
date: 2025-06-09T20:05:08.020Z
- commits:
- subject: Remove `request` dependency
hash: d47abf072ddf1f6529f3d4a14e07436def58df61
body: ""
footer:
Change-type: patch
change-type: patch
author: myarmolinsky
nested: []
- subject: Replace `request` usage with `got`
hash: 8502c4db4bb211a70c682dbc1b85df56f01f2d93
body: ""
footer:
Change-type: patch
change-type: patch
author: myarmolinsky
nested: []
version: 22.0.6
title: ""
date: 2025-06-02T12:27:11.068Z
- commits:
- subject: Bump etcher-sdk to v9.1.4
hash: 0b0e24c9b29ef4bcb6a577ca85708171cc2421c7
body: |
Update etcher-sdk from 9.1.0 to 9.1.4
footer:
Change-type: patch
change-type: patch
author: Otavio Jacobi
nested:
- commits:
- subject: Run `npm audit fix` which should only do non-breaking changes
hash: 22aaacc0744e41989706c968c4efc8767d30b7a8
body: ""
footer:
Change-type: patch
change-type: patch
author: Otavio Jacobi
nested: []
version: etcher-sdk-9.1.4
title: ""
date: 2025-05-29T08:57:28.785Z
- commits:
- subject: Embed config.json with a fixed timestamp to enable consistent checksums
hash: 83e67a4089ec39023c39fe79fe59021237797c85
body: >
Previously the timestamp was changing each time which meant the
checksum would be different every time even if the rest of the
contents
were identical. Changing this to a fixed timestamp avoids that
change
such that only the contents matter.
footer:
Change-type: patch
change-type: patch
author: Pagan Gazzard
nested: []
version: etcher-sdk-9.1.3
title: ""
date: 2025-02-17T12:48:33.911Z
- commits:
- subject: Update dependency unzip-stream to v0.3.2 [SECURITY]
hash: c243e56e4189bee7391943a3325a3c1465c62fd1
body: |
Update unzip-stream from 0.3.1 to 0.3.2
footer:
Change-type: patch
change-type: patch
author: Self-hosted Renovate Bot
nested: []
version: etcher-sdk-9.1.2
title: ""
date: 2024-10-09T08:52:13.524Z
- commits:
- subject: "patch: add EXLOCK flag for windows"
hash: 915feeeceff83249f87a6a0a1656986791206136
body: |
Signed-off-by: Talha Can Havadar <havadartalha@gmail.com>
run prettier for changed files
footer:
Signed-off-by: Talha Can Havadar <havadartalha@gmail.com>
signed-off-by: Talha Can Havadar <havadartalha@gmail.com>
author: Talha Can Havadar
nested: []
version: etcher-sdk-9.1.1
title: ""
date: 2024-10-09T08:24:06.706Z
version: 22.0.5
title: ""
date: 2025-05-29T15:47:31.891Z
- commits:
- subject: "tests: Replace request with got"
hash: a7a408a5c7dcf06b770e8df85e250bfed5a09f75
body: ""
footer:
Change-type: patch
change-type: patch
author: Otavio Jacobi
nested: []
- subject: "deploy-legacy: Replace request with got"
hash: e5877c7de917e377082328ee8ab0b502593c9719
body: ""
footer:
Change-type: patch
change-type: patch
author: Otavio Jacobi
nested: []
version: 22.0.4
title: ""
date: 2025-05-29T13:19:01.228Z
- commits:
- subject: Bump sentry to v9
hash: 5ccee0e4f1ce3bae6963630963cbd72c9c738f77
body: ""
footer:
Change-type: patch
change-type: patch
author: Otavio Jacobi
nested: []
version: 22.0.3
title: ""
date: 2025-05-29T12:09:56.743Z
- commits:
- subject: Fix balena build to work with --nologs
hash: 8d10c1af2a8eddfa146e2d23161c079127eb5546
body: ""
footer:
Change-type: patch
change-type: patch
author: Otavio Jacobi
nested: []
version: 22.0.2
title: ""
date: 2025-05-28T19:32:15.230Z
- commits:
- subject: "DeviceAPI: Move away from `request` in favor of BalenaSdk request"
hash: 3396ba5a971d2ae16552576d65dff953031f01ee

View File

@ -4,67 +4,6 @@ All notable changes to this project will be documented in this file
automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY!
This project adheres to [Semantic Versioning](http://semver.org/).
## 22.1.1 - 2025-06-19
* Deploy: Limit the submitted error_message of images that fail to build to 1000 characters [Thodoris Greasidis]
## 22.1.0 - 2025-06-09
* Add support for node 22 [Otavio Jacobi]
<details>
<summary> Bump etcher-sdk to v10.0.0 [Otavio Jacobi] </summary>
> ### etcher-sdk-10.0.0 - 2025-06-02
>
> * Drop support to node18 and add support to node 22 & 24 [Otavio Jacobi]
>
</details>
## 22.0.6 - 2025-06-02
* Remove `request` dependency [myarmolinsky]
* Replace `request` usage with `got` [myarmolinsky]
## 22.0.5 - 2025-05-29
<details>
<summary> Bump etcher-sdk to v9.1.4 [Otavio Jacobi] </summary>
> ### etcher-sdk-9.1.4 - 2025-05-29
>
> * Run `npm audit fix` which should only do non-breaking changes [Otavio Jacobi]
>
> ### etcher-sdk-9.1.3 - 2025-02-17
>
> * Embed config.json with a fixed timestamp to enable consistent checksums [Pagan Gazzard]
>
> ### etcher-sdk-9.1.2 - 2024-10-09
>
> * Update dependency unzip-stream to v0.3.2 [SECURITY] [Self-hosted Renovate Bot]
>
> ### etcher-sdk-9.1.1 - 2024-10-09
>
> * patch: add EXLOCK flag for windows [Talha Can Havadar]
>
</details>
## 22.0.4 - 2025-05-29
* tests: Replace request with got [Otavio Jacobi]
* deploy-legacy: Replace request with got [Otavio Jacobi]
## 22.0.3 - 2025-05-29
* Bump sentry to v9 [Otavio Jacobi]
## 22.0.2 - 2025-05-28
* Fix balena build to work with --nologs [Otavio Jacobi]
## 22.0.1 - 2025-05-28
* DeviceAPI: Move away from `request` in favor of BalenaSdk request [myarmolinsky]

View File

@ -77,8 +77,8 @@ If you are a Node.js developer, you may wish to install the balena CLI via [npm]
The npm installation involves building native (platform-specific) binary modules, which require
some development tools to be installed first, as follows.
> **The balena CLI currently requires Node.js version >=20.6.0**
> **Versions 23 and later are not yet fully supported.**
> **The balena CLI currently requires Node.js version ^20.6.0**
> **Versions 21 and later are not yet fully supported.**
### Install development tools
@ -88,7 +88,7 @@ some development tools to be installed first, as follows.
$ sudo apt-get update && sudo apt-get -y install curl python3 git make g++
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
$ . ~/.bashrc
$ nvm install 22
$ nvm install 20
```
The `curl` command line above uses
@ -105,7 +105,7 @@ recommended.
```sh
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
$ . ~/.bashrc
$ nvm install 22
$ nvm install 20
```
#### **Windows** (not WSL)
@ -113,7 +113,7 @@ $ nvm install 22
Install:
* If you'd like the ability to switch between Node.js versions, install
- Node.js v22 from the [Nodejs.org releases page](https://nodejs.org/en/download/releases/).
- Node.js v20 from the [Nodejs.org releases page](https://nodejs.org/en/download/releases/).
[nvm-windows](https://github.com/coreybutler/nvm-windows#node-version-manager-nvm-for-windows)
instead.
* The [MSYS2 shell](https://www.msys2.org/), which provides `git`, `make`, `g++` and more:

1744
npm-shrinkwrap.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "balena-cli",
"version": "22.1.1",
"version": "22.0.1",
"description": "The official balena Command Line Interface",
"main": "./build/app.js",
"homepage": "https://github.com/balena-io/balena-cli",
@ -72,7 +72,7 @@
"author": "Balena Inc. (https://balena.io/)",
"license": "Apache-2.0",
"engines": {
"node": ">=20.6.0 <23"
"node": "^20.6.0"
},
"oclif": {
"bin": "balena",
@ -168,9 +168,9 @@
"@balena/env-parsing": "^1.1.8",
"@balena/es-version": "^1.0.1",
"@oclif/core": "^4.1.0",
"@sentry/node": "^9.0.0",
"@sentry/node": "^6.16.1",
"balena-config-json": "^4.2.7",
"balena-device-init": "^8.1.11",
"balena-device-init": "^8.1.3",
"balena-errors": "^4.7.3",
"balena-image-fs": "^7.5.2",
"balena-preload": "^18.0.4",
@ -191,7 +191,7 @@
"docker-progress": "^5.1.3",
"dockerode": "^4.0.5",
"ejs": "^3.1.6",
"etcher-sdk": "^10.0.0",
"etcher-sdk": "9.1.0",
"express": "^4.17.2",
"fast-boot2": "^1.1.0",
"fast-levenshtein": "^3.0.0",
@ -219,8 +219,8 @@
"prettyjson": "^1.2.5",
"progress-stream": "^2.0.0",
"reconfix": "^1.0.0-v0-1-0-fork-46760acff4d165f5238bfac5e464256ef1944476",
"resin-cli-form": "^4.0.0",
"resin-cli-visuals": "^3.0.0",
"resin-cli-form": "^3.0.0",
"resin-cli-visuals": "^2.0.1",
"resin-doodles": "^0.2.0",
"resin-stream-logger": "^0.1.2",
"rimraf": "^3.0.2",
@ -248,6 +248,6 @@
}
},
"versionist": {
"publishedAt": "2025-06-19T09:32:53.877Z"
"publishedAt": "2025-05-28T17:00:46.792Z"
}
}

View File

@ -34,14 +34,18 @@ export const setupSentry = onceAsync(async () => {
const config = await import('./config');
const Sentry = await import('@sentry/node');
Sentry.init({
autoSessionTracking: false,
dsn: config.sentryDsn,
release: packageJSON.version,
});
Sentry.getCurrentScope().setExtras({
is_pkg: !!(process as any).pkg,
node_version: process.version,
platform: process.platform,
Sentry.configureScope((scope) => {
scope.setExtras({
is_pkg: !!(process as any).pkg,
node_version: process.version,
platform: process.platform,
});
});
return Sentry.getCurrentHub();
});
async function checkNodeVersion() {

View File

@ -38,11 +38,11 @@ import { stripIndent } from './utils/lazy';
export async function trackCommand(commandSignature: string) {
try {
let Sentry: typeof import('@sentry/node');
let scope: import('@sentry/node').Scope;
if (!process.env.BALENARC_NO_SENTRY) {
Sentry = await import('@sentry/node');
scope = Sentry.getCurrentScope();
scope.setExtra('command', commandSignature);
Sentry.configureScope((scope) => {
scope.setExtra('command', commandSignature);
});
}
const { getCachedUsername } = await import('./utils/bootstrap');
let username: string | undefined;
@ -52,9 +52,11 @@ export async function trackCommand(commandSignature: string) {
// ignore
}
if (!process.env.BALENARC_NO_SENTRY) {
scope!.setUser({
id: username,
username,
Sentry!.configureScope((scope) => {
scope.setUser({
id: username,
username,
});
});
}
if (

View File

@ -1322,9 +1322,6 @@ async function pushAndUpdateServiceImages(
}
}
// Error messages are limited to 300KB characters in the API, so we truncate longer ones.
const MAX_ERROR_MESSAGE_LENGTH = 300_000;
async function pushServiceImages(
docker: Dockerode,
logger: Logger,
@ -1347,34 +1344,23 @@ async function pushServiceImages(
delete serviceImage.build_log;
}
// These are the only update-able image fields in bC atm, and passing
// the whole image object in v7+ would result the allowlist to reject the request.
const imagePayload = _.pick(serviceImage, [
'end_timestamp',
'project_type',
'error_message',
'build_log',
'push_timestamp',
'status',
'content_hash',
'dockerfile',
'image_size',
]);
if (
typeof imagePayload.error_message === 'string' &&
imagePayload.error_message.length > MAX_ERROR_MESSAGE_LENGTH
) {
logger.logDebug(
`Truncating error message of image ${serviceImage.is_stored_at__image_location} to ${MAX_ERROR_MESSAGE_LENGTH} characters.`,
);
imagePayload.error_message = imagePayload.error_message.substring(
0,
MAX_ERROR_MESSAGE_LENGTH,
);
}
await releaseMod.updateImage(pineClient, serviceImage.id, imagePayload);
await releaseMod.updateImage(
pineClient,
serviceImage.id,
// These are the only update-able image fields in bC atm, and passing
// the whole image object in v7+ would result the allowlist to reject the request.
_.pick(serviceImage, [
'end_timestamp',
'project_type',
'error_message',
'build_log',
'push_timestamp',
'status',
'content_hash',
'dockerfile',
'image_size',
]),
);
},
);
}
@ -1610,9 +1596,7 @@ function buildProgressAdapter(inline: boolean) {
return;
}
// We want to keep the regex match instead of startsWith as it also works with buffers
// eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
if (!/^Successfully tagged /.test(str)) {
if (!str.startsWith('Successfully tagged ')) {
const match = stepRegex.exec(str);
if (match) {
step = match[1];

View File

@ -109,6 +109,9 @@ const uploadToPromise = (
});
});
/**
* @returns {Promise<{ buildId: number }>}
*/
const uploadImage = async function (
imageStream: NodeJS.ReadableStream & { length: number },
token: string,

View File

@ -118,7 +118,7 @@ async function installQemu(arch: string, qemuPath: string) {
}
});
got.stream
.get(qemuUrl)
.get(qemuUrl, { throwHttpErrors: false })
.on('error', reject)
.pipe(zlib.createGunzip())
.on('error', reject)

View File

@ -16,8 +16,6 @@ limitations under the License.
import type { BalenaSDK } from 'balena-sdk';
import * as JSONStream from 'JSONStream';
import * as readline from 'readline';
import type { PlainResponse } from 'got';
import type got from 'got';
import type { RegistrySecrets } from '@balena/compose/dist/multibuild';
import type * as Stream from 'stream';
import streamToPromise = require('stream-to-promise');
@ -27,6 +25,8 @@ import { ExpectedError, SIGINTError } from '../errors';
import { tarDirectory } from './compose_ts';
import { getVisuals, stripIndent } from './lazy';
import Logger = require('./logger');
import type { PlainResponse } from 'got';
import type got from 'got';
const globalLogger = Logger.getLogger();
@ -338,6 +338,12 @@ async function getTarStream(build: RemoteBuild): Promise<Stream.Readable> {
/**
* Initiate a POST HTTP request to the remote builder and add some event
* listeners.
*
* ¡! Note: this function must be synchronous because of a bug in the `request`
* library that requires the following two steps to take place in the same
* iteration of Node's event loop: (1) adding a listener for the 'response'
* event and (2) calling request.pipe():
* https://github.com/request/request/issues/887
*/
async function createRemoteBuildRequest(
build: RemoteBuild,

View File

@ -61,19 +61,17 @@ describe('Login server:', function () {
server.shutdown();
});
async function testLogin({
verb = 'post',
...opt
}: {
async function testLogin(opt: {
expectedBody: string;
expectedErrorMsg?: string;
expectedStatusCode: number;
expectedToken: string;
urlPath?: string;
verb?: 'post' | 'put';
verb?: 'get' | 'post';
}) {
opt.urlPath = opt.urlPath ?? addr.urlPath;
const res = await got[verb](
const request = opt.verb != null ? got[opt.verb] : got.post;
const res = await request(
`http://${addr.host}:${addr.port}${opt.urlPath}`,
{
form: {
@ -113,16 +111,6 @@ describe('Login server:', function () {
});
});
it('should get 404 if not using the correct verb', async () => {
await testLogin({
expectedBody: 'Not found',
expectedStatusCode: 404,
expectedToken: tokens.johndoe.token,
expectedErrorMsg: 'Unknown path or verb',
verb: 'put',
});
});
describe('given the token authenticates with the server', function () {
beforeEach(function () {
this.loginIfTokenValidStub = sinon.stub(utils, 'loginIfTokenValid');

View File

@ -442,93 +442,6 @@ describe('balena build', function () {
});
});
it('should create the expected tar stream (docker-compose --nologs)', async () => {
const projectPath = path.join(projectsPath, 'docker-compose', 'basic');
const service1Dockerfile = (
await fs.readFile(
path.join(projectPath, 'service1', 'Dockerfile.template'),
'utf8',
)
).replace('%%BALENA_MACHINE_NAME%%', 'nuc');
const expectedFilesByService: ExpectedTarStreamFilesByService = {
service1: {
Dockerfile: {
contents: service1Dockerfile,
fileSize: service1Dockerfile.length,
type: 'file',
},
'Dockerfile.template': { fileSize: 144, type: 'file' },
'file1.sh': { fileSize: 12, type: 'file' },
},
service2: {
'Dockerfile-alt': { fileSize: 13, type: 'file' },
'file2-crlf.sh': {
fileSize: isWindows ? 12 : 14,
testStream: isWindows ? expectStreamNoCRLF : undefined,
type: 'file',
},
'src/file1.sh': { fileSize: 12, type: 'file' },
},
};
const responseFilename = 'build-POST.json';
const responseBody = await fs.readFile(
path.join(dockerResponsePath, responseFilename),
'utf8',
);
const expectedQueryParamsByService = {
service1: Object.entries(
_.merge({}, commonComposeQueryParams, {
buildargs: {
COMPOSE_ARG: 'A',
barg: 'b',
SERVICE1_VAR: 'This is a service specific variable',
},
cachefrom: ['my/img1', 'my/img2'],
}),
),
service2: Object.entries(
_.merge({}, commonComposeQueryParamsIntel, {
buildargs: {
COMPOSE_ARG: 'A',
barg: 'b',
},
cachefrom: ['my/img1', 'my/img2'],
dockerfile: 'Dockerfile-alt',
}),
),
};
const expectedResponseLines: string[] = [
...commonResponseLines[responseFilename],
...getDockerignoreWarn1(
[path.join(projectPath, 'service2', '.dockerignore')],
'build',
),
];
if (isWindows) {
expectedResponseLines.push(
`[Info] Converting line endings CRLF -> LF for file: ${path.join(
projectPath,
'service2',
'file2-crlf.sh',
)}`,
);
}
docker.expectGetInfo({});
docker.expectGetManifestNucAlpine();
docker.expectGetManifestBusybox();
await testDockerBuildStream({
commandLine: `build ${projectPath} --deviceType nuc --arch amd64 -B COMPOSE_ARG=A -B barg=b --cache-from my/img1,my/img2 --nologs`,
dockerMock: docker,
expectedFilesByService,
expectedQueryParamsByService,
expectedResponseLines,
projectPath,
responseBody,
responseCode: 200,
services: ['service1', 'service2'],
});
});
it('should create the expected tar stream (docker-compose, --multi-dockerignore)', async () => {
const projectPath = path.join(projectsPath, 'docker-compose', 'basic');
const service1Dockerfile = (

View File

@ -27,7 +27,7 @@ import * as sinon from 'sinon';
import { BalenaAPIMock } from '../nock/balena-api-mock';
import { expectStreamNoCRLF, testDockerBuildStream } from '../docker-build';
import { DockerMock, dockerResponsePath } from '../nock/docker-mock';
import { cleanOutput, runCommand } from '../helpers';
import { cleanOutput, runCommand, switchSentry } from '../helpers';
import type {
ExpectedTarStreamFiles,
ExpectedTarStreamFilesByService,
@ -262,6 +262,7 @@ describe('balena deploy', function () {
});
it('should update a release with status="failed" on error (single container)', async () => {
let sentryStatus: boolean | undefined;
const projectPath = path.join(projectsPath, 'no-docker-compose', 'basic');
const expectedFiles: ExpectedTarStreamFiles = {
'src/.dockerignore': { fileSize: 16, type: 'file' },
@ -318,6 +319,7 @@ describe('balena deploy', function () {
api.expectPostImageLabel();
try {
sentryStatus = await switchSentry(false);
sinon.stub(process, 'exit');
await testDockerBuildStream({
@ -335,8 +337,9 @@ describe('balena deploy', function () {
});
expect(failedImagePatchRequests).to.equal(maxRequestRetries);
} finally {
// We mock process.exit and need to force cast it to a SinonStub to restore it
(process.exit as unknown as sinon.SinonStub).restore();
await switchSentry(sentryStatus);
// @ts-expect-error claims restore does not exist
process.exit.restore();
}
});

View File

@ -417,3 +417,15 @@ export function deepJsonParse(data: any): any {
}
return data;
}
export async function switchSentry(
enabled: boolean | undefined,
): Promise<boolean | undefined> {
const balenaCLI = await import('../build/app');
const sentryOpts = (await balenaCLI.setupSentry()).getClient()?.getOptions();
if (sentryOpts) {
const sentryStatus = sentryOpts.enabled;
sentryOpts.enabled = enabled;
return sentryStatus;
}
}

View File

@ -41,18 +41,23 @@ export class BuilderMock extends NockMock {
checkBuildRequestBody: (requestBody: string | Buffer) => Promise<void>;
}) {
this.optPost(/^\/v3\/build($|[(?])/, opts).reply(
async function (uri, requestBody) {
await opts.checkURI(uri);
if (typeof requestBody === 'string') {
const gzipped = Buffer.from(requestBody, 'hex');
const gunzipped = await gunzipAsync(gzipped);
await opts.checkBuildRequestBody(gunzipped);
return [opts.responseCode, opts.responseBody];
} else {
throw new Error(
`unexpected requestBody type "${typeof requestBody}"`,
);
async function (uri, requestBody, callback) {
let error: Error | null = null;
try {
await opts.checkURI(uri);
if (typeof requestBody === 'string') {
const gzipped = Buffer.from(requestBody, 'hex');
const gunzipped = await gunzipAsync(gzipped);
await opts.checkBuildRequestBody(gunzipped);
} else {
throw new Error(
`unexpected requestBody type "${typeof requestBody}"`,
);
}
} catch (err) {
error = err;
}
callback(error, [opts.responseCode, opts.responseBody]);
},
);
}

View File

@ -81,14 +81,21 @@ export class DockerMock extends NockMock {
this.optPost(
new RegExp(`^/build\\?(|.+&)${qs.stringify({ t: opts.tag })}&`),
opts,
).reply(async function (uri, requestBody) {
await opts.checkURI(uri);
if (typeof requestBody === 'string') {
await opts.checkBuildRequestBody(requestBody);
return [opts.responseCode, opts.responseBody];
} else {
throw new Error(`unexpected requestBody type "${typeof requestBody}"`);
).reply(async function (uri, requestBody, cb) {
let error: Error | null = null;
try {
await opts.checkURI(uri);
if (typeof requestBody === 'string') {
await opts.checkBuildRequestBody(requestBody);
} else {
throw new Error(
`unexpected requestBody type "${typeof requestBody}"`,
);
}
} catch (err) {
error = err;
}
cb(error, [opts.responseCode, opts.responseBody]);
});
}

View File

@ -63,7 +63,7 @@ describe('detectEncoding() function', function () {
it('should correctly detect the encoding of a few selected files', async () => {
const sampleBinary = [
'drivelist/build/Release/drivelist.node',
'mountutils/prebuilds/linux-x64/mountutils.node',
'mountutils/build/Release/MountUtils.node',
];
const sampleText = [
'node_modules/.bin/mocha',