mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-06-24 10:35:39 +00:00
Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
2b76a3999f | |||
ebbdb6f96a |
2
.github/actions/publish/action.yml
vendored
2
.github/actions/publish/action.yml
vendored
@ -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'
|
||||
|
2
.github/actions/test/action.yml
vendored
2
.github/actions/test/action.yml
vendored
@ -15,7 +15,7 @@ inputs:
|
||||
# --- custom environment
|
||||
NODE_VERSION:
|
||||
type: string
|
||||
default: '22.x'
|
||||
default: '20.x'
|
||||
VERBOSE:
|
||||
type: string
|
||||
default: "true"
|
||||
|
@ -1,54 +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
|
||||
|
18
CHANGELOG.md
18
CHANGELOG.md
@ -4,24 +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]
|
||||
|
@ -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:
|
||||
|
808
npm-shrinkwrap.json
generated
808
npm-shrinkwrap.json
generated
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "balena-cli",
|
||||
"version": "22.1.1",
|
||||
"version": "22.0.6",
|
||||
"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",
|
||||
@ -153,7 +153,7 @@
|
||||
"mocha": "^10.6.0",
|
||||
"mock-fs": "^5.2.0",
|
||||
"mock-require": "^3.0.3",
|
||||
"nock": "^14.0.4",
|
||||
"nock": "^15.0.0-beta.3",
|
||||
"oclif": "^4.17.0",
|
||||
"rewire": "^7.0.0",
|
||||
"simple-git": "^3.14.1",
|
||||
@ -170,7 +170,7 @@
|
||||
"@oclif/core": "^4.1.0",
|
||||
"@sentry/node": "^9.0.0",
|
||||
"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.4",
|
||||
"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-06-02T12:27:11.982Z"
|
||||
}
|
||||
}
|
||||
|
@ -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',
|
||||
]),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ describe('Utils:', async function () {
|
||||
});
|
||||
});
|
||||
|
||||
return describe('given the token does authenticate with the server', function () {
|
||||
describe('given the token does authenticate with the server', function () {
|
||||
beforeEach(function () {
|
||||
this.balenaAuthIsLoggedInStub = sinon.stub(balena.auth, 'isLoggedIn');
|
||||
return this.balenaAuthIsLoggedInStub.resolves(true);
|
||||
@ -118,7 +118,7 @@ describe('Utils:', async function () {
|
||||
return this.balenaAuthIsLoggedInStub.restore();
|
||||
});
|
||||
|
||||
return it('should eventually be true', function () {
|
||||
it('should eventually be true', function () {
|
||||
const promise = utils.loginIfTokenValid(tokens.johndoe.token);
|
||||
return expect(promise).to.eventually.be.true;
|
||||
});
|
||||
|
@ -20,7 +20,6 @@ import type { Request as ReleaseRequest } from '@balena/compose/dist/release';
|
||||
import { expect } from 'chai';
|
||||
import { promises as fs } from 'fs';
|
||||
import * as _ from 'lodash';
|
||||
import type * as nock from 'nock';
|
||||
import * as path from 'path';
|
||||
import * as sinon from 'sinon';
|
||||
|
||||
@ -181,8 +180,8 @@ describe('balena deploy', function () {
|
||||
];
|
||||
|
||||
api.expectPostRelease({
|
||||
inspectRequest: (_uri: string, requestBody: nock.Body) => {
|
||||
const body = requestBody.valueOf() as Partial<ReleaseRequest>;
|
||||
inspectRequest: async (request: Request) => {
|
||||
const body = (await request.json()) as Partial<ReleaseRequest>;
|
||||
expect(body.contract).to.deep.equal({
|
||||
name: 'testContract',
|
||||
type: 'sw.application',
|
||||
@ -232,8 +231,8 @@ describe('balena deploy', function () {
|
||||
];
|
||||
|
||||
api.expectPostRelease({
|
||||
inspectRequest: (_uri: string, requestBody: nock.Body) => {
|
||||
const body = requestBody.valueOf() as Partial<ReleaseRequest>;
|
||||
inspectRequest: async (request: Request) => {
|
||||
const body = (await request.json()) as Partial<ReleaseRequest>;
|
||||
expect(body.contract).to.deep.equal({
|
||||
name: 'testContract',
|
||||
type: 'sw.application',
|
||||
@ -298,21 +297,21 @@ describe('balena deploy', function () {
|
||||
statusCode: 500,
|
||||
// b/c failed requests are retried
|
||||
times: maxRequestRetries,
|
||||
inspectRequest: (_uri, requestBody) => {
|
||||
const imageBody = requestBody as Partial<
|
||||
inspectRequest: async (request: Request) => {
|
||||
const body = (await request.json()) as Partial<
|
||||
import('@balena/compose/dist/release/models').ImageModel
|
||||
>;
|
||||
expect(imageBody.status).to.equal('success');
|
||||
expect(body.status).to.equal('success');
|
||||
failedImagePatchRequests++;
|
||||
},
|
||||
});
|
||||
// Check that the CLI patches the release with status="failed"
|
||||
api.expectPatchRelease({
|
||||
inspectRequest: (_uri, requestBody) => {
|
||||
const releaseBody = requestBody as Partial<
|
||||
inspectRequest: async (request: Request) => {
|
||||
const body = (await request.json()) as Partial<
|
||||
import('@balena/compose/dist/release/models').ReleaseModel
|
||||
>;
|
||||
expect(releaseBody.status).to.equal('failed');
|
||||
expect(body.status).to.equal('failed');
|
||||
},
|
||||
});
|
||||
api.expectPostImageLabel();
|
||||
@ -386,8 +385,8 @@ describe('balena deploy', function () {
|
||||
let succesfullImagePatchRequests = 0;
|
||||
api
|
||||
.optPatch(/^\/v7\/image($|[(?])/, { times: maxRequestRetries })
|
||||
.reply((_uri, requestBody) => {
|
||||
const imageBody = requestBody as Partial<
|
||||
.reply(async (request) => {
|
||||
const imageBody = (await request.json()) as Partial<
|
||||
import('@balena/compose/dist/release/models').ImageModel
|
||||
>;
|
||||
expect(imageBody.status).to.equal('success');
|
||||
|
@ -61,12 +61,15 @@ export class BalenaAPIMock extends NockMock {
|
||||
}
|
||||
|
||||
public expectDownloadConfig(opts: ScopeOpts = {}) {
|
||||
this.optPost('/download-config', opts).reply(200, (_uri, body) => {
|
||||
let deviceType = 'raspberrypi3';
|
||||
if (typeof body === 'object' && 'deviceType' in body) {
|
||||
deviceType = body.deviceType;
|
||||
}
|
||||
return JSON.parse(`{
|
||||
this.optPost('/download-config', opts).reply(
|
||||
200,
|
||||
async (request: Request) => {
|
||||
const body = await request.json();
|
||||
let deviceType = 'raspberrypi3';
|
||||
if (typeof body === 'object' && 'deviceType' in body) {
|
||||
deviceType = body.deviceType;
|
||||
}
|
||||
return JSON.parse(`{
|
||||
"applicationId":1301645,
|
||||
"deviceType":"${deviceType}",
|
||||
"userId":43699,
|
||||
@ -79,7 +82,8 @@ export class BalenaAPIMock extends NockMock {
|
||||
"deltaEndpoint":"https://delta.balena-cloud.com",
|
||||
"apiKey":"nothingtoseehere"
|
||||
}`);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
public expectApplicationProvisioning(opts: ScopeOpts = {}) {
|
||||
@ -284,8 +288,8 @@ export class BalenaAPIMock extends NockMock {
|
||||
|
||||
public expectGetAppServiceVars(opts: ScopeOpts = {}) {
|
||||
this.optGet(/^\/v\d+\/service_environment_variable($|\?)/, opts).reply(
|
||||
function (uri, _requestBody) {
|
||||
const match = uri.match(/service_name%20eq%20%27(.+?)%27/);
|
||||
function (request) {
|
||||
const match = request.url.match(/service_name%20eq%20%27(.+?)%27/);
|
||||
const serviceName = match?.[1] || undefined;
|
||||
let varArray: any[];
|
||||
if (serviceName) {
|
||||
@ -332,8 +336,8 @@ export class BalenaAPIMock extends NockMock {
|
||||
this.optGet(
|
||||
/^\/v\d+\/device_service_environment_variable($|\?)/,
|
||||
opts,
|
||||
).reply(function (uri, _requestBody) {
|
||||
const match = uri.match(/service_name%20eq%20%27(.+?)%27/);
|
||||
).reply(function (request) {
|
||||
const match = request.url.match(/service_name%20eq%20%27(.+?)%27/);
|
||||
const serviceName = match?.[1] || undefined;
|
||||
let varArray: any[];
|
||||
if (serviceName) {
|
||||
|
@ -16,12 +16,7 @@
|
||||
*/
|
||||
|
||||
import * as path from 'path';
|
||||
import * as zlib from 'zlib';
|
||||
|
||||
import { NockMock } from './nock-mock';
|
||||
import { promisify } from 'util';
|
||||
|
||||
const gunzipAsync = promisify(zlib.gunzip);
|
||||
|
||||
export const builderResponsePath = path.normalize(
|
||||
path.join(__dirname, '..', 'test-data', 'builder-response'),
|
||||
@ -40,20 +35,17 @@ export class BuilderMock extends NockMock {
|
||||
checkURI: (uri: string) => Promise<void> | void;
|
||||
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}"`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
this.optPost(/^\/v3\/build($|[(?])/, opts).reply(async function (
|
||||
request: Request,
|
||||
) {
|
||||
await opts.checkURI(request.url);
|
||||
const requestBody = await request.text();
|
||||
if (typeof requestBody === 'string') {
|
||||
await opts.checkBuildRequestBody(requestBody);
|
||||
} else {
|
||||
throw new Error(`unexpected requestBody type "${typeof requestBody}"`);
|
||||
}
|
||||
return [opts.responseCode, opts.responseBody];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -81,14 +81,15 @@ 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);
|
||||
).reply(async function (request) {
|
||||
await opts.checkURI(request.url);
|
||||
const requestBody = await request.text();
|
||||
if (typeof requestBody === 'string') {
|
||||
await opts.checkBuildRequestBody(requestBody);
|
||||
return [opts.responseCode, opts.responseBody];
|
||||
} else {
|
||||
throw new Error(`unexpected requestBody type "${typeof requestBody}"`);
|
||||
}
|
||||
return [opts.responseCode, opts.responseBody];
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -100,47 +100,28 @@ export class NockMock {
|
||||
return this.optMethod('post', uri, opts);
|
||||
}
|
||||
|
||||
protected inspectNoOp(_uri: string, _requestBody: nock.Body): void {
|
||||
return undefined;
|
||||
protected inspectNoOp(_request: Request): void | Promise<void> {
|
||||
return;
|
||||
}
|
||||
|
||||
protected getInspectedReplyBodyFunction(
|
||||
inspectRequest: (uri: string, requestBody: nock.Body) => void,
|
||||
inspectRequest: (request: Request) => void | Promise<void>,
|
||||
replyBody: nock.ReplyBody,
|
||||
) {
|
||||
return function (
|
||||
this: nock.ReplyFnContext,
|
||||
uri: string,
|
||||
requestBody: nock.Body,
|
||||
cb: (err: NodeJS.ErrnoException | null, result: nock.ReplyBody) => void,
|
||||
) {
|
||||
try {
|
||||
inspectRequest(uri, requestBody);
|
||||
} catch (err) {
|
||||
cb(err, '');
|
||||
}
|
||||
cb(null, replyBody);
|
||||
return async function (request: Request): Promise<nock.ReplyBody> {
|
||||
await inspectRequest(request);
|
||||
return replyBody;
|
||||
};
|
||||
}
|
||||
|
||||
protected getInspectedReplyFileFunction(
|
||||
inspectRequest: (uri: string, requestBody: nock.Body) => void,
|
||||
inspectRequest: (request: Request) => void | Promise<void>,
|
||||
replyBodyFile: string,
|
||||
) {
|
||||
return function (
|
||||
this: nock.ReplyFnContext,
|
||||
uri: string,
|
||||
requestBody: nock.Body,
|
||||
cb: (err: NodeJS.ErrnoException | null, result: nock.ReplyBody) => void,
|
||||
) {
|
||||
try {
|
||||
inspectRequest(uri, requestBody);
|
||||
} catch (err) {
|
||||
cb(err, '');
|
||||
}
|
||||
|
||||
return async function (request: Request): Promise<nock.ReplyBody> {
|
||||
await inspectRequest(request);
|
||||
const replyBody = fs.readFileSync(replyBodyFile);
|
||||
cb(null, replyBody);
|
||||
return replyBody;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -48,8 +48,8 @@ export class SupervisorMock extends NockMock {
|
||||
}, 10);
|
||||
},
|
||||
});
|
||||
this.optGet('/v2/local/logs', opts).reply((_uri, _reqBody, cb) => {
|
||||
cb(null, [200, chunkedStream]);
|
||||
this.optGet('/v2/local/logs', opts).reply(() => {
|
||||
return [200, chunkedStream];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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',
|
||||
|
Reference in New Issue
Block a user