mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-06-25 02:47:55 +00:00
Compare commits
1 Commits
v20.2.8
...
allow-cust
Author | SHA1 | Date | |
---|---|---|---|
eed4a385a9 |
@ -882,6 +882,7 @@ Examples:
|
|||||||
|
|
||||||
$ balena build --fleet myFleet
|
$ balena build --fleet myFleet
|
||||||
$ balena build ./source/ --fleet myorg/myfleet
|
$ balena build ./source/ --fleet myorg/myfleet
|
||||||
|
$ balena build ./source/ --fleet myorg/myfleet --docker-compose my-custom-compose.yml
|
||||||
$ balena build --deviceType raspberrypi3 --arch armv7hf --emulated
|
$ balena build --deviceType raspberrypi3 --arch armv7hf --emulated
|
||||||
$ balena build --docker /var/run/docker.sock --fleet myFleet # Linux, Mac
|
$ balena build --docker /var/run/docker.sock --fleet myFleet # Linux, Mac
|
||||||
$ balena build --docker //./pipe/docker_engine --fleet myFleet # Windows
|
$ balena build --docker //./pipe/docker_engine --fleet myFleet # Windows
|
||||||
@ -915,6 +916,10 @@ Use QEMU for ARM architecture emulation during the image build
|
|||||||
|
|
||||||
Alternative Dockerfile name/path, relative to the source folder
|
Alternative Dockerfile name/path, relative to the source folder
|
||||||
|
|
||||||
|
#### --docker-compose DOCKER-COMPOSE
|
||||||
|
|
||||||
|
Alternative compose yml file, relative to the source folder
|
||||||
|
|
||||||
#### --nologs
|
#### --nologs
|
||||||
|
|
||||||
Hide the image build log output (produce less verbose output)
|
Hide the image build log output (produce less verbose output)
|
||||||
@ -1087,6 +1092,7 @@ Examples:
|
|||||||
|
|
||||||
$ balena deploy myFleet
|
$ balena deploy myFleet
|
||||||
$ balena deploy myorg/myfleet --build --source myBuildDir/
|
$ balena deploy myorg/myfleet --build --source myBuildDir/
|
||||||
|
$ balena deploy myorg/myfleet --builld --source myBuildDir/ --docker-compose my-custom-compose.yml
|
||||||
$ balena deploy myorg/myfleet --build --source myBuildDir/ --note "this is the note for this release"
|
$ balena deploy myorg/myfleet --build --source myBuildDir/ --note "this is the note for this release"
|
||||||
$ balena deploy myorg/myfleet myRepo/myImage
|
$ balena deploy myorg/myfleet myRepo/myImage
|
||||||
$ balena deploy myFleet myRepo/myImage --release-tag key1 "" key2 "value2 with spaces"
|
$ balena deploy myFleet myRepo/myImage --release-tag key1 "" key2 "value2 with spaces"
|
||||||
@ -1140,6 +1146,10 @@ Use QEMU for ARM architecture emulation during the image build
|
|||||||
|
|
||||||
Alternative Dockerfile name/path, relative to the source folder
|
Alternative Dockerfile name/path, relative to the source folder
|
||||||
|
|
||||||
|
#### --docker-compose DOCKER-COMPOSE
|
||||||
|
|
||||||
|
Alternative compose yml file, relative to the source folder
|
||||||
|
|
||||||
#### --nologs
|
#### --nologs
|
||||||
|
|
||||||
Hide the image build log output (produce less verbose output)
|
Hide the image build log output (produce less verbose output)
|
||||||
@ -3281,6 +3291,7 @@ Examples:
|
|||||||
$ balena push myFleet -s <source directory>
|
$ balena push myFleet -s <source directory>
|
||||||
$ balena push myFleet --source <source directory> --note "this is the note for this release"
|
$ balena push myFleet --source <source directory> --note "this is the note for this release"
|
||||||
$ balena push myFleet --release-tag key1 "" key2 "value2 with spaces"
|
$ balena push myFleet --release-tag key1 "" key2 "value2 with spaces"
|
||||||
|
$ balena push myorg/myfleet --docker-compose my-custom-compose.yml
|
||||||
$ balena push myorg/myfleet
|
$ balena push myorg/myfleet
|
||||||
|
|
||||||
$ balena push 10.0.0.1
|
$ balena push 10.0.0.1
|
||||||
@ -3315,6 +3326,10 @@ suspected issues with the balenaCloud backend.
|
|||||||
|
|
||||||
Alternative Dockerfile name/path, relative to the source folder
|
Alternative Dockerfile name/path, relative to the source folder
|
||||||
|
|
||||||
|
#### --docker-compose DOCKER-COMPOSE
|
||||||
|
|
||||||
|
Alternative compose yml file, relative to the source folder
|
||||||
|
|
||||||
#### -c, --nocache
|
#### -c, --nocache
|
||||||
|
|
||||||
Don't use cached layers of previously built images for this project. This
|
Don't use cached layers of previously built images for this project. This
|
||||||
|
@ -67,6 +67,7 @@ ${dockerignoreHelp}
|
|||||||
public static examples = [
|
public static examples = [
|
||||||
'$ balena build --fleet myFleet',
|
'$ balena build --fleet myFleet',
|
||||||
'$ balena build ./source/ --fleet myorg/myfleet',
|
'$ balena build ./source/ --fleet myorg/myfleet',
|
||||||
|
'$ balena build ./source/ --fleet myorg/myfleet --docker-compose my-custom-compose.yml',
|
||||||
'$ balena build --deviceType raspberrypi3 --arch armv7hf --emulated',
|
'$ balena build --deviceType raspberrypi3 --arch armv7hf --emulated',
|
||||||
'$ balena build --docker /var/run/docker.sock --fleet myFleet # Linux, Mac',
|
'$ balena build --docker /var/run/docker.sock --fleet myFleet # Linux, Mac',
|
||||||
'$ balena build --docker //./pipe/docker_engine --fleet myFleet # Windows',
|
'$ balena build --docker //./pipe/docker_engine --fleet myFleet # Windows',
|
||||||
|
@ -98,6 +98,7 @@ ${dockerignoreHelp}
|
|||||||
public static examples = [
|
public static examples = [
|
||||||
'$ balena deploy myFleet',
|
'$ balena deploy myFleet',
|
||||||
'$ balena deploy myorg/myfleet --build --source myBuildDir/',
|
'$ balena deploy myorg/myfleet --build --source myBuildDir/',
|
||||||
|
'$ balena deploy myorg/myfleet --builld --source myBuildDir/ --docker-compose my-custom-compose.yml',
|
||||||
'$ balena deploy myorg/myfleet --build --source myBuildDir/ --note "this is the note for this release"',
|
'$ balena deploy myorg/myfleet --build --source myBuildDir/ --note "this is the note for this release"',
|
||||||
'$ balena deploy myorg/myfleet myRepo/myImage',
|
'$ balena deploy myorg/myfleet myRepo/myImage',
|
||||||
'$ balena deploy myFleet myRepo/myImage --release-tag key1 "" key2 "value2 with spaces"',
|
'$ balena deploy myFleet myRepo/myImage --release-tag key1 "" key2 "value2 with spaces"',
|
||||||
|
@ -78,6 +78,7 @@ export default class PushCmd extends Command {
|
|||||||
'$ balena push myFleet -s <source directory>',
|
'$ balena push myFleet -s <source directory>',
|
||||||
'$ balena push myFleet --source <source directory> --note "this is the note for this release"',
|
'$ balena push myFleet --source <source directory> --note "this is the note for this release"',
|
||||||
'$ balena push myFleet --release-tag key1 "" key2 "value2 with spaces"',
|
'$ balena push myFleet --release-tag key1 "" key2 "value2 with spaces"',
|
||||||
|
'$ balena push myorg/myfleet --docker-compose my-custom-compose.yml',
|
||||||
'$ balena push myorg/myfleet',
|
'$ balena push myorg/myfleet',
|
||||||
'',
|
'',
|
||||||
'$ balena push 10.0.0.1',
|
'$ balena push 10.0.0.1',
|
||||||
@ -121,6 +122,10 @@ export default class PushCmd extends Command {
|
|||||||
description:
|
description:
|
||||||
'Alternative Dockerfile name/path, relative to the source folder',
|
'Alternative Dockerfile name/path, relative to the source folder',
|
||||||
}),
|
}),
|
||||||
|
'docker-compose': Flags.string({
|
||||||
|
description:
|
||||||
|
'Alternative compose yml file, relative to the source folder',
|
||||||
|
}),
|
||||||
nocache: Flags.boolean({
|
nocache: Flags.boolean({
|
||||||
description: stripIndent`
|
description: stripIndent`
|
||||||
Don't use cached layers of previously built images for this project. This
|
Don't use cached layers of previously built images for this project. This
|
||||||
@ -365,6 +370,7 @@ export default class PushCmd extends Command {
|
|||||||
dockerfilePath,
|
dockerfilePath,
|
||||||
registrySecrets,
|
registrySecrets,
|
||||||
multiDockerignore: options['multi-dockerignore'],
|
multiDockerignore: options['multi-dockerignore'],
|
||||||
|
composefileName: options['docker-compose'],
|
||||||
nocache: options.nocache,
|
nocache: options.nocache,
|
||||||
pull: options.pull,
|
pull: options.pull,
|
||||||
noParentCheck: options['noparent-check'],
|
noParentCheck: options['noparent-check'],
|
||||||
|
@ -47,6 +47,12 @@ export class NoPortsDefinedError extends ExpectedError {
|
|||||||
|
|
||||||
export class SIGINTError extends ExpectedError {}
|
export class SIGINTError extends ExpectedError {}
|
||||||
|
|
||||||
|
export class CompositionFileNotFoundError extends ExpectedError {
|
||||||
|
constructor(filePath: string) {
|
||||||
|
super(`Composition file not found at: "${filePath}"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* instanceOf is a more reliable implementation of the plain `instanceof`
|
* instanceOf is a more reliable implementation of the plain `instanceof`
|
||||||
* typescript operator, for use with TypedError errors when the error
|
* typescript operator, for use with TypedError errors when the error
|
||||||
|
2
lib/utils/compose-types.d.ts
vendored
2
lib/utils/compose-types.d.ts
vendored
@ -53,6 +53,7 @@ export interface TaggedImage {
|
|||||||
export interface ComposeOpts {
|
export interface ComposeOpts {
|
||||||
convertEol: boolean;
|
convertEol: boolean;
|
||||||
dockerfilePath?: string;
|
dockerfilePath?: string;
|
||||||
|
composefileName?: string;
|
||||||
inlineLogs?: boolean;
|
inlineLogs?: boolean;
|
||||||
multiDockerignore: boolean;
|
multiDockerignore: boolean;
|
||||||
noParentCheck: boolean;
|
noParentCheck: boolean;
|
||||||
@ -65,6 +66,7 @@ export interface ComposeCliFlags {
|
|||||||
emulated: boolean;
|
emulated: boolean;
|
||||||
dockerfile?: string;
|
dockerfile?: string;
|
||||||
nologs: boolean;
|
nologs: boolean;
|
||||||
|
'docker-compose'?: string;
|
||||||
'multi-dockerignore': boolean;
|
'multi-dockerignore': boolean;
|
||||||
'noparent-check': boolean;
|
'noparent-check': boolean;
|
||||||
'registry-secrets'?: RegistrySecrets;
|
'registry-secrets'?: RegistrySecrets;
|
||||||
|
@ -40,6 +40,7 @@ export function generateOpts(options: {
|
|||||||
dockerfile?: string;
|
dockerfile?: string;
|
||||||
'multi-dockerignore': boolean;
|
'multi-dockerignore': boolean;
|
||||||
'noparent-check': boolean;
|
'noparent-check': boolean;
|
||||||
|
'docker-compose'?: string;
|
||||||
}): Promise<ComposeOpts> {
|
}): Promise<ComposeOpts> {
|
||||||
const { promises: fs } = require('fs') as typeof import('fs');
|
const { promises: fs } = require('fs') as typeof import('fs');
|
||||||
return fs.realpath(options.source || '.').then((projectPath) => ({
|
return fs.realpath(options.source || '.').then((projectPath) => ({
|
||||||
@ -49,6 +50,7 @@ export function generateOpts(options: {
|
|||||||
convertEol: !options['noconvert-eol'],
|
convertEol: !options['noconvert-eol'],
|
||||||
dockerfilePath: options.dockerfile,
|
dockerfilePath: options.dockerfile,
|
||||||
multiDockerignore: !!options['multi-dockerignore'],
|
multiDockerignore: !!options['multi-dockerignore'],
|
||||||
|
composefileName: options['docker-compose'],
|
||||||
noParentCheck: options['noparent-check'],
|
noParentCheck: options['noparent-check'],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ import type * as MultiBuild from '@balena/compose/dist/multibuild';
|
|||||||
import * as semver from 'semver';
|
import * as semver from 'semver';
|
||||||
import type { Duplex, Readable } from 'stream';
|
import type { Duplex, Readable } from 'stream';
|
||||||
import type { Pack } from 'tar-stream';
|
import type { Pack } from 'tar-stream';
|
||||||
import { ExpectedError } from '../errors';
|
import { CompositionFileNotFoundError, ExpectedError } from '../errors';
|
||||||
import {
|
import {
|
||||||
BuiltImage,
|
BuiltImage,
|
||||||
ComposeOpts,
|
ComposeOpts,
|
||||||
@ -128,7 +128,11 @@ export async function loadProject(
|
|||||||
composeStr = compose.defaultComposition(image);
|
composeStr = compose.defaultComposition(image);
|
||||||
} else {
|
} else {
|
||||||
logger.logDebug('Resolving project...');
|
logger.logDebug('Resolving project...');
|
||||||
[composeName, composeStr] = await resolveProject(logger, opts.projectPath);
|
[composeName, composeStr] = await resolveProject({
|
||||||
|
logger,
|
||||||
|
projectRoot: opts.projectPath,
|
||||||
|
compositionFile: opts.composefileName,
|
||||||
|
});
|
||||||
|
|
||||||
if (composeName) {
|
if (composeName) {
|
||||||
if (opts.dockerfilePath) {
|
if (opts.dockerfilePath) {
|
||||||
@ -198,33 +202,55 @@ async function mergeDevComposeOverlay(
|
|||||||
return composeStr;
|
return composeStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getDefaultCompositionFileName(
|
||||||
|
projectRoot: string,
|
||||||
|
): Promise<string | undefined> {
|
||||||
|
for (const fname of compositionFileNames) {
|
||||||
|
if (await exists(path.join(projectRoot, fname))) {
|
||||||
|
return fname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ResolveProjectParameters {
|
||||||
|
logger: Logger;
|
||||||
|
projectRoot: string;
|
||||||
|
quiet?: boolean;
|
||||||
|
compositionFile?: string;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Look into the given directory for valid compose files and return
|
* Look into the given directory for valid compose files and return
|
||||||
* the contents of the first one found.
|
* the contents of the first one found.
|
||||||
*/
|
*/
|
||||||
async function resolveProject(
|
async function resolveProject({
|
||||||
logger: Logger,
|
logger,
|
||||||
projectRoot: string,
|
projectRoot,
|
||||||
quiet = false,
|
quiet = false,
|
||||||
): Promise<[string, string]> {
|
compositionFile,
|
||||||
let composeFileName = '';
|
}: ResolveProjectParameters): Promise<[string, string]> {
|
||||||
|
logger.logError(`Iam on resolve project and have ${compositionFile}`);
|
||||||
|
const composeFileName =
|
||||||
|
compositionFile ?? (await getDefaultCompositionFileName(projectRoot));
|
||||||
let composeFileContents = '';
|
let composeFileContents = '';
|
||||||
for (const fname of compositionFileNames) {
|
|
||||||
const fpath = path.join(projectRoot, fname);
|
if (composeFileName == null) {
|
||||||
if (await exists(fpath)) {
|
throw new CompositionFileNotFoundError(projectRoot);
|
||||||
logger.logDebug(`${fname} file found at "${projectRoot}"`);
|
}
|
||||||
composeFileName = fname;
|
|
||||||
try {
|
const fpath = path.join(projectRoot, composeFileName);
|
||||||
composeFileContents = await fs.readFile(fpath, 'utf8');
|
if (!(await exists(fpath))) {
|
||||||
} catch (err) {
|
throw new CompositionFileNotFoundError(fpath);
|
||||||
logger.logError(`Error reading composition file "${fpath}":\n${err}`);
|
}
|
||||||
throw err;
|
|
||||||
}
|
logger.logDebug(`Using composition file at "${fpath}"`);
|
||||||
break;
|
try {
|
||||||
}
|
composeFileContents = await fs.readFile(fpath, 'utf8');
|
||||||
|
} catch (err) {
|
||||||
|
logger.logError(`Error reading composition file "${fpath}":\n${err}`);
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
if (!quiet && !composeFileName) {
|
if (!quiet && !composeFileName) {
|
||||||
logger.logInfo(`No "docker-compose.yml" file found at "${projectRoot}"`);
|
logger.logInfo(`No composition file found at "${projectRoot}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [composeFileName, composeFileContents];
|
return [composeFileName, composeFileContents];
|
||||||
@ -680,15 +706,17 @@ async function loadBuildMetatada(
|
|||||||
export async function getServiceDirsFromComposition(
|
export async function getServiceDirsFromComposition(
|
||||||
sourceDir: string,
|
sourceDir: string,
|
||||||
composition?: Composition,
|
composition?: Composition,
|
||||||
|
compositionFile?: string,
|
||||||
): Promise<Dictionary<string>> {
|
): Promise<Dictionary<string>> {
|
||||||
const { createProject } = await import('./compose');
|
const { createProject } = await import('./compose');
|
||||||
const serviceDirs: Dictionary<string> = {};
|
const serviceDirs: Dictionary<string> = {};
|
||||||
if (!composition) {
|
if (!composition) {
|
||||||
const [, composeStr] = await resolveProject(
|
const [, composeStr] = await resolveProject({
|
||||||
Logger.getLogger(),
|
logger: Logger.getLogger(),
|
||||||
sourceDir,
|
projectRoot: sourceDir,
|
||||||
true,
|
quiet: true,
|
||||||
);
|
compositionFile,
|
||||||
|
});
|
||||||
if (composeStr) {
|
if (composeStr) {
|
||||||
composition = createProject(sourceDir, composeStr).composition;
|
composition = createProject(sourceDir, composeStr).composition;
|
||||||
}
|
}
|
||||||
@ -1652,6 +1680,9 @@ export const composeCliFlags = {
|
|||||||
description:
|
description:
|
||||||
'Alternative Dockerfile name/path, relative to the source folder',
|
'Alternative Dockerfile name/path, relative to the source folder',
|
||||||
}),
|
}),
|
||||||
|
'docker-compose': Flags.string({
|
||||||
|
description: 'Alternative compose yml file, relative to the source folder',
|
||||||
|
}),
|
||||||
nologs: Flags.boolean({
|
nologs: Flags.boolean({
|
||||||
description:
|
description:
|
||||||
'Hide the image build log output (produce less verbose output)',
|
'Hide the image build log output (produce less verbose output)',
|
||||||
|
@ -56,6 +56,7 @@ export interface DeviceDeployOptions {
|
|||||||
deviceHost: string;
|
deviceHost: string;
|
||||||
devicePort?: number;
|
devicePort?: number;
|
||||||
dockerfilePath?: string;
|
dockerfilePath?: string;
|
||||||
|
composefileName?: string;
|
||||||
registrySecrets: RegistrySecrets;
|
registrySecrets: RegistrySecrets;
|
||||||
multiDockerignore: boolean;
|
multiDockerignore: boolean;
|
||||||
nocache: boolean;
|
nocache: boolean;
|
||||||
@ -182,6 +183,7 @@ export async function deployToDevice(opts: DeviceDeployOptions): Promise<void> {
|
|||||||
const project = await loadProject(globalLogger, {
|
const project = await loadProject(globalLogger, {
|
||||||
convertEol: opts.convertEol,
|
convertEol: opts.convertEol,
|
||||||
dockerfilePath: opts.dockerfilePath,
|
dockerfilePath: opts.dockerfilePath,
|
||||||
|
composefileName: opts.composefileName,
|
||||||
multiDockerignore: opts.multiDockerignore,
|
multiDockerignore: opts.multiDockerignore,
|
||||||
noParentCheck: opts.noParentCheck,
|
noParentCheck: opts.noParentCheck,
|
||||||
projectName: 'local',
|
projectName: 'local',
|
||||||
|
Reference in New Issue
Block a user