mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-06-24 10:35:39 +00:00
Compare commits
2 Commits
v21.1.2
...
example-mo
Author | SHA1 | Date | |
---|---|---|---|
357866e345 | |||
629ac9e5e9 |
@ -22,7 +22,7 @@ _balena() {
|
||||
key_cmds=( add rm )
|
||||
local_cmds=( configure flash )
|
||||
os_cmds=( build-config configure download initialize versions )
|
||||
release_cmds=( finalize invalidate validate )
|
||||
release_cmds=( export finalize import invalidate validate )
|
||||
tag_cmds=( rm set )
|
||||
|
||||
|
||||
|
@ -21,7 +21,7 @@ _balena_complete()
|
||||
key_cmds="add rm"
|
||||
local_cmds="configure flash"
|
||||
os_cmds="build-config configure download initialize versions"
|
||||
release_cmds="finalize invalidate validate"
|
||||
release_cmds="export finalize import invalidate validate"
|
||||
tag_cmds="rm set"
|
||||
|
||||
|
||||
|
@ -282,7 +282,9 @@ are encouraged to regularly update the balena CLI to the latest version.
|
||||
|
||||
- Releases
|
||||
|
||||
- [release export <commitorid>](#release-export-commitorid)
|
||||
- [release finalize <commitorid>](#release-finalize-commitorid)
|
||||
- [release import <file> <fleet>](#release-import-file-fleet)
|
||||
- [release <commitorid>](#release-commitorid)
|
||||
- [release invalidate <commitorid>](#release-invalidate-commitorid)
|
||||
- [release validate <commitorid>](#release-validate-commitorid)
|
||||
@ -3345,6 +3347,37 @@ The notes for this release
|
||||
|
||||
# Releases
|
||||
|
||||
## release export <commitOrId>
|
||||
|
||||
Exporting a release to a file allows you to import an exact
|
||||
copy of the original release into another app.
|
||||
|
||||
If the SemVer of a release is provided using the --version option,
|
||||
the first argument is assumed to be the fleet's slug.
|
||||
|
||||
Only successful releases can be exported.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena release export a777f7345fe3d655c1c981aa642e5555 -o ../path/to/release.tar
|
||||
$ balena release export myOrg/myFleet --version 1.2.3 -o ../path/to/release.tar
|
||||
|
||||
### Arguments
|
||||
|
||||
#### COMMITORID
|
||||
|
||||
commit, ID, or version of the release to export
|
||||
|
||||
### Options
|
||||
|
||||
#### -o, --output OUTPUT
|
||||
|
||||
output path
|
||||
|
||||
#### --version VERSION
|
||||
|
||||
version of the release to export from the specified fleet
|
||||
|
||||
## release finalize <commitOrId>
|
||||
|
||||
Finalize a release. Releases can be "draft" or "final", and this command
|
||||
@ -3371,6 +3404,40 @@ the commit or ID of the release to finalize
|
||||
|
||||
### Options
|
||||
|
||||
## release import <file> <fleet>
|
||||
|
||||
is automatically omitted when importing a release. The backend will auto-increment
|
||||
the revision field of the imported release if a release exists with the same semver.
|
||||
A release will not be imported if a successful release with the same commit already
|
||||
exists.
|
||||
|
||||
To export a release to a file, use 'balena release export'.
|
||||
|
||||
Use the --override-version option to specify the version
|
||||
of the imported release, overriding the one saved in the file.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena release import ../path/to/release.tar myFleet
|
||||
$ balena release import ../path/to/release.tar myOrg/myFleet
|
||||
$ balena release import ../path/to/release.tar myOrg/myFleet --override-version 1.2.3
|
||||
|
||||
### Arguments
|
||||
|
||||
#### BUNDLE
|
||||
|
||||
path to a file, e.g. "./release.tar"
|
||||
|
||||
#### FLEET
|
||||
|
||||
fleet that the release will be imported to, e.g. "myOrg/myFleet"
|
||||
|
||||
### Options
|
||||
|
||||
#### --override-version OVERRIDE-VERSION
|
||||
|
||||
Imports this release with the specified version overriding the version in the file.
|
||||
|
||||
## release <commitOrId>
|
||||
|
||||
The --json option is recommended when scripting the output of this command,
|
||||
|
89
npm-shrinkwrap.json
generated
89
npm-shrinkwrap.json
generated
@ -14,6 +14,7 @@
|
||||
"@balena/dockerignore": "^1.0.2",
|
||||
"@balena/env-parsing": "^1.1.8",
|
||||
"@balena/es-version": "^1.0.1",
|
||||
"@balena/release-bundle": "^0.5.2",
|
||||
"@oclif/core": "^4.0.8",
|
||||
"@resin.io/valid-email": "^0.1.0",
|
||||
"@sentry/node": "^6.16.1",
|
||||
@ -1656,6 +1657,40 @@
|
||||
"web-streams-polyfill": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@balena/release-bundle": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@balena/release-bundle/-/release-bundle-0.5.2.tgz",
|
||||
"integrity": "sha512-q2ji3Pky9RGeztApTBaoZEF2R8FSiHsFutIvvlmA0ggJKgATxNNavZd4ueYtlK/Nl53g9vUrKmiwzCVgw9rDRw==",
|
||||
"dependencies": {
|
||||
"@balena/resource-bundle": "^0.8.3",
|
||||
"balena-semver": "^2.3.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"balena-sdk": "^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@balena/resource-bundle": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@balena/resource-bundle/-/resource-bundle-0.8.3.tgz",
|
||||
"integrity": "sha512-WKkeZkZIcrey1l08G1gS60EQCYtTZsOwwmnRhvmjnmWmUAcqa3Z9WqYDqM7ePbFO/pdo9Cd0JK0Xr+pgj3A8ng==",
|
||||
"dependencies": {
|
||||
"auth-header": "^1.0.0",
|
||||
"tar-stream": "^3.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@balena/resource-bundle/node_modules/tar-stream": {
|
||||
"version": "3.1.7",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz",
|
||||
"integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==",
|
||||
"dependencies": {
|
||||
"b4a": "^1.6.4",
|
||||
"fast-fifo": "^1.2.0",
|
||||
"streamx": "^2.15.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@balena/udif": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@balena/udif/-/udif-1.1.2.tgz",
|
||||
@ -2079,9 +2114,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui/node_modules/ansi-regex": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
|
||||
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
||||
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@ -3894,9 +3929,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.16.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.4.tgz",
|
||||
"integrity": "sha512-ioyQ1zK9aGEomJ45zz8S8IdzElyxhvP1RVWnPrXDf6wFaUb+kk1tEcVVJkF7RPGM0VWI7cp5U57oCPIn5iN1qg==",
|
||||
"version": "20.16.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.5.tgz",
|
||||
"integrity": "sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.19.2"
|
||||
}
|
||||
@ -5327,6 +5362,11 @@
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/auth-header": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/auth-header/-/auth-header-1.0.0.tgz",
|
||||
"integrity": "sha512-CPPazq09YVDUNNVWo4oSPTQmtwIzHusZhQmahCKvIsk0/xH6U3QsMAv3sM+7+Q0B1K2KJ/Q38OND317uXs4NHA=="
|
||||
},
|
||||
"node_modules/available-typed-arrays": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
|
||||
@ -5681,9 +5721,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/balena-sdk/node_modules/@types/node": {
|
||||
"version": "18.19.49",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.49.tgz",
|
||||
"integrity": "sha512-ALCeIR6n0nQ7j0FUF1ycOhrp6+XutJWqEu/vtdEqXFUQwkBfgUA5cEg3ZNmjWGF/ZYA/FcF9QMkL55Ar0O6UrA==",
|
||||
"version": "18.19.50",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz",
|
||||
"integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==",
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
@ -7128,11 +7168,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.6",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
|
||||
"integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
|
||||
"version": "4.3.7",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
|
||||
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
@ -12650,12 +12690,6 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/mocha/node_modules/strip-json-comments": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
||||
@ -12876,9 +12910,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
},
|
||||
"node_modules/multicast-dns": {
|
||||
"version": "7.2.5",
|
||||
@ -14776,9 +14810,9 @@
|
||||
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
|
||||
},
|
||||
"node_modules/pump": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.1.tgz",
|
||||
"integrity": "sha512-2ynnAmUu45oUSq51AQbeugLkMSKaz8FqVpZ6ykTqzOVkzXe8u/ezkGsYrFJqKZx+D9cVxoDrSbR7CeAwxFa5cQ==",
|
||||
"dependencies": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
@ -15800,11 +15834,6 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/send/node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
},
|
||||
"node_modules/sentence-case": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz",
|
||||
|
@ -196,6 +196,7 @@
|
||||
"@balena/dockerignore": "^1.0.2",
|
||||
"@balena/env-parsing": "^1.1.8",
|
||||
"@balena/es-version": "^1.0.1",
|
||||
"@balena/release-bundle": "^0.5.2",
|
||||
"@oclif/core": "^4.0.8",
|
||||
"@resin.io/valid-email": "^0.1.0",
|
||||
"@sentry/node": "^6.16.1",
|
||||
|
116
src/commands/release/export.ts
Normal file
116
src/commands/release/export.ts
Normal file
@ -0,0 +1,116 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2016-2024 Balena Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { commitOrIdArg } from '.';
|
||||
import { Flags } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import { create } from '@balena/release-bundle';
|
||||
import * as fs from 'fs/promises';
|
||||
import * as semver from 'balena-semver';
|
||||
import { ExpectedError } from '../../errors';
|
||||
|
||||
export default class ReleaseExportCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
Exports a release into a file.
|
||||
|
||||
Exporting a release to a file allows you to import an exact
|
||||
copy of the original release into another app.
|
||||
|
||||
If the SemVer of a release is provided using the --version option,
|
||||
the first argument is assumed to be the fleet's slug.
|
||||
|
||||
Only successful releases can be exported.
|
||||
`;
|
||||
public static examples = [
|
||||
'$ balena release export a777f7345fe3d655c1c981aa642e5555 -o ../path/to/release.tar',
|
||||
'$ balena release export myOrg/myFleet --version 1.2.3 -o ../path/to/release.tar',
|
||||
];
|
||||
|
||||
public static usage = 'release export <commitOrId>';
|
||||
|
||||
public static flags = {
|
||||
output: Flags.string({
|
||||
description: 'output path',
|
||||
char: 'o',
|
||||
required: true,
|
||||
}),
|
||||
version: Flags.string({
|
||||
description: 'version of the release to export from the specified fleet',
|
||||
}),
|
||||
help: cf.help,
|
||||
};
|
||||
|
||||
public static args = {
|
||||
commitOrId: commitOrIdArg({
|
||||
description: 'commit, ID, or version of the release to export',
|
||||
required: true,
|
||||
}),
|
||||
};
|
||||
|
||||
public static authenticated = true;
|
||||
|
||||
public async run() {
|
||||
const { args: params, flags: options } = await this.parse(ReleaseExportCmd);
|
||||
|
||||
const balena = getBalenaSdk();
|
||||
|
||||
let release: balenaSdk.Release;
|
||||
if (typeof options.version === 'string') {
|
||||
const application = params.commitOrId;
|
||||
const parsedVersion = semver.parse(options.version);
|
||||
if (parsedVersion == null) {
|
||||
throw new ExpectedError(
|
||||
`Release of ${application} with version ${options.version} could not be exported; version must be valid SemVer.`,
|
||||
);
|
||||
} else {
|
||||
const rawVersion =
|
||||
parsedVersion.build.length === 0
|
||||
? parsedVersion.version
|
||||
: `${parsedVersion.version}+${parsedVersion.build[0]}`;
|
||||
release = await balena.models.release.get(
|
||||
{ application, rawVersion },
|
||||
{ $select: ['id'] },
|
||||
);
|
||||
}
|
||||
} else {
|
||||
release = await balena.models.release.get(params.commitOrId, {
|
||||
$select: ['id'],
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const releaseBundle = await create({
|
||||
sdk: balena,
|
||||
releaseId: release.id,
|
||||
});
|
||||
await fs.writeFile(options.output, releaseBundle);
|
||||
const versionInfo =
|
||||
typeof options.version === 'string'
|
||||
? ` version ${options.version}`
|
||||
: '';
|
||||
console.log(
|
||||
`Release ${params.commitOrId}${versionInfo} has been exported to ${options.output}.`,
|
||||
);
|
||||
} catch (error) {
|
||||
throw new ExpectedError(
|
||||
`Release ${params.commitOrId} could not be exported: ${error.message}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
103
src/commands/release/import.ts
Normal file
103
src/commands/release/import.ts
Normal file
@ -0,0 +1,103 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2016-2024 Balena Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Flags, Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import { apply } from '@balena/release-bundle';
|
||||
import { createReadStream } from 'fs';
|
||||
import { ExpectedError } from '../../errors';
|
||||
|
||||
export default class ReleaseImportCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
Imports a release from a file to an app or fleet. The revision field of the release
|
||||
is automatically omitted when importing a release. The backend will auto-increment
|
||||
the revision field of the imported release if a release exists with the same semver.
|
||||
A release will not be imported if a successful release with the same commit already
|
||||
exists.
|
||||
|
||||
To export a release to a file, use 'balena release export'.
|
||||
|
||||
Use the --override-version option to specify the version
|
||||
of the imported release, overriding the one saved in the file.
|
||||
`;
|
||||
public static examples = [
|
||||
'$ balena release import ../path/to/release.tar myFleet',
|
||||
'$ balena release import ../path/to/release.tar myOrg/myFleet',
|
||||
'$ balena release import ../path/to/release.tar myOrg/myFleet --override-version 1.2.3',
|
||||
];
|
||||
|
||||
public static usage = 'release import <file> <fleet>';
|
||||
|
||||
public static flags = {
|
||||
'override-version': Flags.string({
|
||||
description:
|
||||
'Imports this release with the specified version overriding the version in the file.',
|
||||
required: false,
|
||||
}),
|
||||
help: cf.help,
|
||||
};
|
||||
|
||||
public static args = {
|
||||
bundle: Args.string({
|
||||
required: true,
|
||||
description: 'path to a file, e.g. "./release.tar"',
|
||||
}),
|
||||
fleet: Args.string({
|
||||
required: true,
|
||||
description:
|
||||
'fleet that the release will be imported to, e.g. "myOrg/myFleet"',
|
||||
}),
|
||||
};
|
||||
|
||||
public static authenticated = true;
|
||||
|
||||
public async run() {
|
||||
const { args: params, flags: options } = await this.parse(ReleaseImportCmd);
|
||||
|
||||
const balena = getBalenaSdk();
|
||||
|
||||
const bundle = createReadStream(params.bundle).on('error', () => {
|
||||
throw new ExpectedError(
|
||||
`Release bundle ${params.bundle} does not exist or is not accessible.`,
|
||||
);
|
||||
});
|
||||
|
||||
try {
|
||||
const application = await balena.models.application.get(params.fleet, {
|
||||
$select: ['id'],
|
||||
});
|
||||
if (application == null) {
|
||||
throw new ExpectedError(`Fleet ${params.fleet} not found.`);
|
||||
}
|
||||
await apply({
|
||||
sdk: balena,
|
||||
application: application.id,
|
||||
stream: bundle,
|
||||
version: options['override-version'],
|
||||
});
|
||||
console.log(
|
||||
`Release bundle ${params.bundle} has been imported to ${params.fleet}.`,
|
||||
);
|
||||
} catch (error) {
|
||||
throw new ExpectedError(
|
||||
`Could not import release bundle ${params.bundle} to fleet ${params.fleet}: ${error.message}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
76
tests/commands/release/export.spec.ts
Normal file
76
tests/commands/release/export.spec.ts
Normal file
@ -0,0 +1,76 @@
|
||||
import * as stream from 'node:stream';
|
||||
import { cleanOutput, runCommand } from '../../helpers';
|
||||
import { BalenaAPIMock } from '../../nock/balena-api-mock';
|
||||
import { expect } from 'chai';
|
||||
import * as mock from 'mock-require';
|
||||
import * as sinon from 'sinon';
|
||||
|
||||
// "itSS" means "it() Skip Standalone"
|
||||
const itSS = process.env.BALENA_CLI_TEST_TYPE === 'standalone' ? it.skip : it;
|
||||
|
||||
describe('export fleet content to a file', function () {
|
||||
let api: BalenaAPIMock;
|
||||
const releaseBundleCreateStub = sinon.stub();
|
||||
|
||||
this.beforeEach(() => {
|
||||
api = new BalenaAPIMock();
|
||||
mock('@balena/release-bundle', {
|
||||
create: releaseBundleCreateStub,
|
||||
});
|
||||
});
|
||||
|
||||
this.afterEach(() => {
|
||||
// Check all expected api calls have been made and clean up.
|
||||
api.done();
|
||||
mock.stop('@balena/release-bundle');
|
||||
});
|
||||
|
||||
itSS('should export a release to a file', async () => {
|
||||
api.expectGetWhoAmI();
|
||||
api.expectGetRelease();
|
||||
releaseBundleCreateStub.resolves(stream.Readable.from('something'));
|
||||
|
||||
const { out, err } = await runCommand(
|
||||
'release export badc0ffe -o /tmp/release.tar.gz',
|
||||
);
|
||||
|
||||
const lines = cleanOutput(out);
|
||||
expect(lines[0]).to.contain(
|
||||
'Release badc0ffe has been exported to /tmp/release.tar.gz.',
|
||||
);
|
||||
expect(err).to.be.empty;
|
||||
});
|
||||
|
||||
itSS('should fail if the create throws an error', async () => {
|
||||
api.expectGetWhoAmI();
|
||||
api.expectGetRelease();
|
||||
releaseBundleCreateStub.rejects(
|
||||
new Error('Something went wrong creating the bundle'),
|
||||
);
|
||||
|
||||
const { err } = await runCommand(
|
||||
'release export badc0ffe -o /tmp/release.tar.gz',
|
||||
);
|
||||
|
||||
expect(cleanOutput(err, true)).to.include(
|
||||
'Release badc0ffe could not be exported: Something went wrong creating the bundle',
|
||||
);
|
||||
});
|
||||
|
||||
itSS('should parse with application slug and version', async () => {
|
||||
api.expectGetWhoAmI();
|
||||
api.expectGetRelease();
|
||||
api.expectGetApplication();
|
||||
releaseBundleCreateStub.resolves(stream.Readable.from('something'));
|
||||
|
||||
const { out, err } = await runCommand(
|
||||
'release export org/superApp -o /tmp/release.tar.gz --version 1.2.3+rev1',
|
||||
);
|
||||
|
||||
const lines = cleanOutput(out);
|
||||
expect(lines[0]).to.contain(
|
||||
'Release org/superApp version 1.2.3+rev1 has been exported to /tmp/release.tar.gz.',
|
||||
);
|
||||
expect(err).to.be.empty;
|
||||
});
|
||||
});
|
@ -205,6 +205,12 @@
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules/@oclif/core/package.json
|
||||
%2: build/commands/push/index.js
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules/@oclif/core/package.json
|
||||
%2: build/commands/release/export.js
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules/@oclif/core/package.json
|
||||
%2: build/commands/release/import.js
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules/@oclif/core/package.json
|
||||
%2: build/commands/release/index.js
|
||||
|
@ -205,6 +205,12 @@
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules/@oclif/core/package.json
|
||||
%2: build/commands/push/index.js
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules/@oclif/core/package.json
|
||||
%2: build/commands/release/export.js
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules/@oclif/core/package.json
|
||||
%2: build/commands/release/import.js
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules/@oclif/core/package.json
|
||||
%2: build/commands/release/index.js
|
||||
|
@ -205,6 +205,12 @@
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules/@oclif/core/package.json
|
||||
%2: build/commands/push/index.js
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules/@oclif/core/package.json
|
||||
%2: build/commands/release/export.js
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules/@oclif/core/package.json
|
||||
%2: build/commands/release/import.js
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules/@oclif/core/package.json
|
||||
%2: build/commands/release/index.js
|
||||
|
@ -205,6 +205,12 @@
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules/@oclif/core/package.json
|
||||
%2: build/commands/push/index.js
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules/@oclif/core/package.json
|
||||
%2: build/commands/release/export.js
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules/@oclif/core/package.json
|
||||
%2: build/commands/release/import.js
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules/@oclif/core/package.json
|
||||
%2: build/commands/release/index.js
|
||||
|
@ -205,6 +205,12 @@
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules\@oclif\core\package.json
|
||||
%2: build\commands\push\index.js
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules\@oclif\core\package.json
|
||||
%2: build\commands\release\export.js
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules\@oclif\core\package.json
|
||||
%2: build\commands\release\import.js
|
||||
> Warning Entry 'main' not found in %1
|
||||
%1: node_modules\@oclif\core\package.json
|
||||
%2: build\commands\release\index.js
|
||||
|
Reference in New Issue
Block a user