diff --git a/lib/commands/deploy/index.ts b/lib/commands/deploy/index.ts index c4be73c0..1fa0232c 100644 --- a/lib/commands/deploy/index.ts +++ b/lib/commands/deploy/index.ts @@ -364,20 +364,13 @@ ${dockerignoreHelp} $select: ['commit'], }); } else { - const [{ id: userId }, auth, apiEndpoint] = await Promise.all([ - sdk.auth.getUserInfo(), - sdk.auth.getToken(), - sdk.settings.get('apiUrl'), - ]); release = await $deployProject( docker, + sdk, logger, project.composition, images, opts.app.id, - userId, - `Bearer ${auth}`, - apiEndpoint, !opts.shouldUploadLogs, composeOpts.projectPath, opts.createAsDraft, diff --git a/lib/utils/compose-types.d.ts b/lib/utils/compose-types.d.ts index 1d8924a2..ab566167 100644 --- a/lib/utils/compose-types.d.ts +++ b/lib/utils/compose-types.d.ts @@ -80,9 +80,7 @@ export interface ComposeProject { } export interface Release { - client: ReturnType< - typeof import('@balena/compose/dist/release').createClient - >; + client: import('@balena/compose').release.Request['client']; release: Pick< ReleaseModel, | 'id' diff --git a/lib/utils/compose.ts b/lib/utils/compose.ts index cfcfd4a4..a9f8d09c 100644 --- a/lib/utils/compose.ts +++ b/lib/utils/compose.ts @@ -121,10 +121,8 @@ const getRequestRetryParameters = (): RetryParametersObj => { }; export const createRelease = async function ( + sdk: SDK.BalenaSDK, logger: Logger, - apiEndpoint: string, - auth: string, - userId: number, appId: number, composition: Composition, draft: boolean, @@ -136,24 +134,32 @@ export const createRelease = async function ( const releaseMod = require('@balena/compose/dist/release') as typeof import('@balena/compose/dist/release'); - const client = releaseMod.createClient({ - apiEndpoint, - auth, - retry: { - ...getRequestRetryParameters(), - onRetry: (err, delayMs, attempt, maxAttempts) => { - const code = err?.statusCode ?? 0; - logger.logDebug( - `API call failed with code ${code}. Attempting retry ${attempt} of ${maxAttempts} in ${ - delayMs / 1000 - } seconds`, - ); + // @ts-expect-error - Once we start using the pinejs-client-core@^6.15.0 types in the SDK's + // pine instance, this ts-expect-error should no longer be needed. + const pinejsClient: import('@balena/compose').release.Request['client'] = + sdk.pine.clone( + { + retry: { + ...getRequestRetryParameters(), + onRetry: (err, delayMs, attempt, maxAttempts) => { + const code = err?.statusCode ?? 0; + logger.logDebug( + `API call failed with code ${code}. Attempting retry ${attempt} of ${maxAttempts} in ${ + delayMs / 1000 + } seconds`, + ); + }, + }, }, - }, - }); + { + // @balena/compose atm works with v6, bump it once @balena/compose moves to v7. + apiVersion: 'v6', + }, + ); + const { id: userId } = await sdk.auth.getUserInfo(); const { release, serviceImages } = await releaseMod.create({ - client, + client: pinejsClient, user: userId, application: appId, composition, @@ -165,7 +171,7 @@ export const createRelease = async function ( }); return { - client, + client: pinejsClient, release: _.pick(release, [ 'id', 'status', diff --git a/lib/utils/compose_ts.ts b/lib/utils/compose_ts.ts index 3a34c7fd..8cb9ae5b 100644 --- a/lib/utils/compose_ts.ts +++ b/lib/utils/compose_ts.ts @@ -1326,9 +1326,7 @@ async function pushAndUpdateServiceImages( async function pushServiceImages( docker: Dockerode, logger: Logger, - pineClient: ReturnType< - typeof import('@balena/compose/dist/release').createClient - >, + pineClient: import('@balena/compose').release.Request['client'], taggedImages: TaggedImage[], token: string, skipLogUpload: boolean, @@ -1353,13 +1351,11 @@ async function pushServiceImages( export async function deployProject( docker: Dockerode, + sdk: BalenaSDK, logger: Logger, composition: Composition, images: BuiltImage[], appId: number, - userId: number, - auth: string, - apiEndpoint: string, skipLogUpload: boolean, projectPath: string, isDraft: boolean, @@ -1378,6 +1374,7 @@ export async function deployProject( Error: the version field in "${contractPath}" is not a valid semver`); } + const apiEndpoint = await sdk.settings.get('apiUrl'); const $release = await runSpinner( tty, @@ -1385,10 +1382,8 @@ export async function deployProject( `${prefix}Creating release...`, () => createRelease( + sdk, logger, - apiEndpoint, - auth, - userId, appId, composition, isDraft, diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index a2efcfbd..b35f4eaa 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -23,7 +23,7 @@ "balena-image-fs": "^7.0.6", "balena-image-manager": "^10.0.1", "balena-preload": "^15.0.6", - "balena-sdk": "^19.7.2", + "balena-sdk": "^19.7.3", "balena-semver": "^2.3.0", "balena-settings-client": "^5.0.2", "balena-settings-storage": "^8.1.0", @@ -1296,9 +1296,9 @@ } }, "node_modules/@babel/template/node_modules/@babel/types": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.8.tgz", - "integrity": "sha512-SkSBEHwwJRU52QEVZBmMBnE5Ux2/6WU1grdYyOhpbCNxbmJrDuDCphBzKZSO3taf0zztp+qkWlymE5tVL5l0TA==", + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", + "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.24.8", @@ -1331,12 +1331,12 @@ } }, "node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.8.tgz", - "integrity": "sha512-47DG+6F5SzOi0uEvK4wMShmn5yY0mVjVJoWTphdY2B4Rx9wHgjK7Yhtr0ru6nE+sn0v38mzrWOlah0p/YlHHOQ==", + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.9.tgz", + "integrity": "sha512-G8v3jRg+z8IwY1jHFxvCNhOPYPterE4XljNgdGTYfSTtzzwjIswIzIaSPSLs3R7yFuqnqNeay5rjICfqVr+/6A==", "dev": true, "dependencies": { - "@babel/types": "^7.24.8", + "@babel/types": "^7.24.9", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" @@ -1346,9 +1346,9 @@ } }, "node_modules/@babel/traverse/node_modules/@babel/types": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.8.tgz", - "integrity": "sha512-SkSBEHwwJRU52QEVZBmMBnE5Ux2/6WU1grdYyOhpbCNxbmJrDuDCphBzKZSO3taf0zztp+qkWlymE5tVL5l0TA==", + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", + "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.24.8", @@ -5750,9 +5750,9 @@ } }, "node_modules/balena-sdk": { - "version": "19.7.2", - "resolved": "https://registry.npmjs.org/balena-sdk/-/balena-sdk-19.7.2.tgz", - "integrity": "sha512-RGqDr10S43kTVlGTaejK6WpEVvW25YP0lIeybIcXchmweg9Mgt/rGJv/gVyLJwdSiw/9Tdgfaul0DTR6nlkD2g==", + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/balena-sdk/-/balena-sdk-19.7.3.tgz", + "integrity": "sha512-O7c+ZVZVSGOlECvkLvi1DWwbKb7bM3UgPaRlCfld0cOcp6X9S+6fcLt9ewOOhF3YsxrBksYOSYBnrmkW9VxqLQ==", "dependencies": { "@balena/es-version": "^1.0.0", "@types/json-schema": "^7.0.9", diff --git a/package.json b/package.json index b641495f..c28af790 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "test:standalone": "npm run build:standalone && npm run test:standalone:fast", "test:standalone:fast": "cross-env BALENA_CLI_TEST_TYPE=standalone mocha --config .mocharc-standalone.js", "test:fast": "npm run build:fast && npm run test:source", + "test:fast-profile": "npm run test:fast -- -- --inspect-brk=0.0.0.0", "test:debug": "cross-env BALENA_CLI_TEST_TYPE=source mocha --inspect-brk=0.0.0.0", "test:only": "npm run build:fast && cross-env BALENA_CLI_TEST_TYPE=source mocha \"tests/**/${npm_config_test}.spec.ts\"", "catch-uncommitted": "ts-node --transpile-only automation/run.ts catch-uncommitted", @@ -211,7 +212,7 @@ "balena-image-fs": "^7.0.6", "balena-image-manager": "^10.0.1", "balena-preload": "^15.0.6", - "balena-sdk": "^19.7.2", + "balena-sdk": "^19.7.3", "balena-semver": "^2.3.0", "balena-settings-client": "^5.0.2", "balena-settings-storage": "^8.1.0", diff --git a/tests/commands/deploy.spec.ts b/tests/commands/deploy.spec.ts index 117b5aa5..d8537524 100644 --- a/tests/commands/deploy.spec.ts +++ b/tests/commands/deploy.spec.ts @@ -276,7 +276,7 @@ describe('balena deploy', function () { ); const expectedResponseLines = ['[Error] Deploy failed']; const errMsg = 'Patch Image Error'; - const expectedErrorLines = [errMsg]; + const expectedErrorLines = [`Request error: ${errMsg}`]; // The SDK should produce an "unexpected" BalenaRequestError, which // causes the CLI to call process.exit() with process.exitCode = 1 const expectedExitCode = 1; diff --git a/tests/nock/balena-api-mock.ts b/tests/nock/balena-api-mock.ts index e0649518..0d50f9d2 100644 --- a/tests/nock/balena-api-mock.ts +++ b/tests/nock/balena-api-mock.ts @@ -162,6 +162,7 @@ export class BalenaAPIMock extends NockMock { inspectRequest, path.join(apiResponsePath, 'release-POST-v6.json'), ), + jHeader, ); }