Update build command for organizations

Change-type: patch
Connects-to: #2119
Signed-off-by: Scott Lowe <scott@balena.io>
This commit is contained in:
Scott Lowe 2020-12-24 12:01:24 +01:00
parent 61b11994b5
commit de0a538abd
4 changed files with 75 additions and 40 deletions

View File

@ -2734,20 +2734,20 @@ answer "yes" to all questions (non interactive use)
## build [source]
Use this command to build an image or a complete multicontainer project with
the provided docker daemon in your development machine or balena device.
(See also the `balena push` command for the option of building images in the
balenaCloud build servers.)
the provided docker daemon in your development machine or balena device.
(See also the `balena push` command for the option of building images in the
balenaCloud build servers.)
You must provide either an application or a device-type/architecture pair.
You must provide either an application or a device-type/architecture pair.
This command will look into the given source directory (or the current working
directory if one isn't specified) for a docker-compose.yml file, and if found,
each service defined in the compose file will be built. If a compose file isn't
found, it will look for a Dockerfile[.template] file (or alternative Dockerfile
specified with the `--dockerfile` option), and if no dockerfile is found, it
will try to generate one.
This command will look into the given source directory (or the current working
directory if one isn't specified) for a docker-compose.yml file, and if found,
each service defined in the compose file will be built. If a compose file isn't
found, it will look for a Dockerfile[.template] file (or alternative Dockerfile
specified with the `--dockerfile` option), and if no dockerfile is found, it
will try to generate one.
REGISTRY SECRETS
REGISTRY SECRETS
The --registry-secrets option specifies a JSON or YAML file containing private
Docker registry usernames and passwords to be used when pulling base images.
Sample registry-secrets YAML file:
@ -2767,9 +2767,11 @@ check: https://github.com/balena-io-examples/sample-gcr-registry-secrets
If the --registry-secrets option is not specified, and a secrets.yml or
secrets.json file exists in the balena directory (usually $HOME/.balena),
this file will be used instead.
this file will be used instead..split('
').join('
')}
DOCKERIGNORE AND GITIGNORE FILES
DOCKERIGNORE AND GITIGNORE FILES
By default, the balena CLI will use a single ".dockerignore" file (if any) at
the project root (--source directory) in order to decide which source files to
exclude from the "build context" (tar stream) sent to balenaCloud, Docker
@ -2819,7 +2821,9 @@ project. If necessary, the effect of the `**/.git` pattern may be modified by
adding counter patterns to the applicable .dockerignore file(s), for example
`!mysubmodule/.git`. For documentation on pattern format, see:
- https://docs.docker.com/engine/reference/builder/#dockerignore-file
- https://www.npmjs.com/package/@balena/dockerignore
- https://www.npmjs.com/package/@balena/dockerignore.split('
').join('
')}
Examples:
@ -2848,7 +2852,7 @@ the type of device this build is for
#### -a, --application APPLICATION
name of the target balena application this build is for
name or slug of the target application this build is for
#### -e, --emulated

View File

@ -17,7 +17,7 @@
import { flags } from '@oclif/command';
import Command from '../command';
import { getBalenaSdk } from '../utils/lazy';
import { getBalenaSdk, stripIndent } from '../utils/lazy';
import * as compose from '../utils/compose';
import type { Application, ApplicationType, BalenaSDK } from 'balena-sdk';
import { dockerignoreHelp, registrySecretsHelp } from '../utils/messages';
@ -25,6 +25,7 @@ import type { ComposeCliFlags, ComposeOpts } from '../utils/compose-types';
import { buildProject, composeCliFlags } from '../utils/compose_ts';
import type { BuildOpts, DockerCliFlags } from '../utils/docker';
import { dockerCliFlags } from '../utils/docker';
import { lowercaseIfSlug } from '../utils/normalization';
interface FlagsDef extends ComposeCliFlags, DockerCliFlags {
arch?: string;
@ -39,27 +40,28 @@ interface ArgsDef {
}
export default class BuildCmd extends Command {
public static description = `\
Build a project locally.
public static description = stripIndent`
Build a project locally.
Use this command to build an image or a complete multicontainer project with
the provided docker daemon in your development machine or balena device.
(See also the \`balena push\` command for the option of building images in the
balenaCloud build servers.)
Use this command to build an image or a complete multicontainer project with
the provided docker daemon in your development machine or balena device.
(See also the \`balena push\` command for the option of building images in the
balenaCloud build servers.)
You must provide either an application or a device-type/architecture pair.
You must provide either an application or a device-type/architecture pair.
This command will look into the given source directory (or the current working
directory if one isn't specified) for a docker-compose.yml file, and if found,
each service defined in the compose file will be built. If a compose file isn't
found, it will look for a Dockerfile[.template] file (or alternative Dockerfile
specified with the \`--dockerfile\` option), and if no dockerfile is found, it
will try to generate one.
This command will look into the given source directory (or the current working
directory if one isn't specified) for a docker-compose.yml file, and if found,
each service defined in the compose file will be built. If a compose file isn't
found, it will look for a Dockerfile[.template] file (or alternative Dockerfile
specified with the \`--dockerfile\` option), and if no dockerfile is found, it
will try to generate one.
${registrySecretsHelp}
${registrySecretsHelp}.split('\n').join('\n\t\t')}
${dockerignoreHelp}.split('\n').join('\n\t\t')}
`;
${dockerignoreHelp}
`;
public static examples = [
'$ balena build --application myApp',
'$ balena build ./source/ --application myApp',
@ -88,8 +90,9 @@ ${dockerignoreHelp}
char: 'd',
}),
application: flags.string({
description: 'name of the target balena application this build is for',
description: 'name or slug of the target application this build is for',
char: 'a',
parse: lowercaseIfSlug,
}),
...composeCliFlags,
...dockerCliFlags,
@ -122,7 +125,7 @@ ${dockerignoreHelp}
await this.validateOptions(options, sdk);
const app = await this.getAppAndResolveArch(options);
const app = await this.getAppAndResolveArch(sdk, options);
const { docker, buildOpts, composeOpts } = await this.prepareBuild(options);
@ -173,10 +176,10 @@ ${dockerignoreHelp}
opts['registry-secrets'] = registrySecrets;
}
protected async getAppAndResolveArch(opts: FlagsDef) {
protected async getAppAndResolveArch(sdk: BalenaSDK, opts: FlagsDef) {
if (opts.application) {
const { getAppWithArch } = await import('../utils/helpers');
const app = await getAppWithArch(opts.application);
const { getAppWithArch } = await import('../utils/sdk');
const app = await getAppWithArch(sdk, opts.application);
opts.arch = app.arch;
opts.deviceType = app.is_for__device_type[0].slug;
return app;

View File

@ -246,9 +246,9 @@ export default class PushCmd extends Command {
}),
gitignore: flags.boolean({
description: stripIndent`
Consider .gitignore files in addition to the .dockerignore file. This reverts
to the CLI v11 behavior/implementation (deprecated) if compatibility is
required until your project can be adapted.`,
Consider .gitignore files in addition to the .dockerignore file. This reverts
to the CLI v11 behavior/implementation (deprecated) if compatibility is
required until your project can be adapted.`,
char: 'g',
default: false,
exclusive: ['multi-dockerignore'],

View File

@ -18,9 +18,12 @@
import type {
Application,
BalenaSDK,
DeviceType,
Organization,
PineOptions,
} from 'balena-sdk';
import { getBalenaSdk } from './lazy';
import * as BalenaSdk from 'balena-sdk';
/**
* Wraps the sdk application.get method,
@ -112,3 +115,28 @@ export async function getOwnOrganizations(
$orderby: 'name asc',
});
}
export async function getAppWithArch(
sdk: BalenaSDK,
appNameOrSlug: string,
): Promise<ApplicationWithDeviceType & { arch: string }> {
const [app, deviceTypes] = await Promise.all([
getApplication(sdk, appNameOrSlug, {
$expand: {
is_for__device_type: { $select: 'slug' },
},
}) as Promise<ApplicationWithDeviceType>,
getBalenaSdk().models.config.getDeviceTypes(),
]);
const _ = await import('lodash');
const config = _.find<BalenaSdk.DeviceTypeJson.DeviceType>(deviceTypes, {
slug: (app.is_for__device_type as DeviceType[])[0].slug,
});
if (!config) {
throw new Error('Could not read application information!');
}
return { ...app, arch: config.arch };
}