mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-02-20 09:26:42 +00:00
v13 preparations: Add feature switch for removal of '--gitignore' (push, build)
Change-type: patch
This commit is contained in:
parent
352fd197b7
commit
d6faf060e6
@ -2926,16 +2926,16 @@ Don't convert line endings from CRLF (Windows format) to LF (Unix format).
|
||||
|
||||
Have each service use its own .dockerignore file. See "balena help push".
|
||||
|
||||
#### -G, --nogitignore
|
||||
|
||||
No-op (default behavior) since balena CLI v12.0.0. See "balena help push".
|
||||
|
||||
#### -g, --gitignore
|
||||
|
||||
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.
|
||||
|
||||
#### -G, --nogitignore
|
||||
|
||||
No-op (default behavior) since balena CLI v12.0.0. See "balena help push".
|
||||
|
||||
#### --release-tag RELEASE-TAG
|
||||
|
||||
Set release tags if the image build is successful (balenaCloud only). Multiple
|
||||
@ -3159,14 +3159,14 @@ 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.
|
||||
|
||||
#### -m, --multi-dockerignore
|
||||
|
||||
Have each service use its own .dockerignore file. See "balena help build".
|
||||
|
||||
#### -G, --nogitignore
|
||||
|
||||
No-op (default behavior) since balena CLI v12.0.0. See "balena help build".
|
||||
|
||||
#### -m, --multi-dockerignore
|
||||
|
||||
Have each service use its own .dockerignore file. See "balena help build".
|
||||
|
||||
#### --noparent-check
|
||||
|
||||
Disable project validation check of 'docker-compose.yml' file in parent folder
|
||||
@ -3398,14 +3398,14 @@ 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.
|
||||
|
||||
#### -m, --multi-dockerignore
|
||||
|
||||
Have each service use its own .dockerignore file. See "balena help build".
|
||||
|
||||
#### -G, --nogitignore
|
||||
|
||||
No-op (default behavior) since balena CLI v12.0.0. See "balena help build".
|
||||
|
||||
#### -m, --multi-dockerignore
|
||||
|
||||
Have each service use its own .dockerignore file. See "balena help build".
|
||||
|
||||
#### --noparent-check
|
||||
|
||||
Disable project validation check of 'docker-compose.yml' file in parent folder
|
||||
|
@ -266,7 +266,7 @@ ${dockerignoreHelp}
|
||||
inlineLogs: composeOpts.inlineLogs,
|
||||
convertEol: composeOpts.convertEol,
|
||||
dockerfilePath: composeOpts.dockerfilePath,
|
||||
nogitignore: composeOpts.nogitignore,
|
||||
nogitignore: composeOpts.nogitignore, // v13: delete this line
|
||||
multiDockerignore: composeOpts.multiDockerignore,
|
||||
});
|
||||
}
|
||||
|
@ -314,7 +314,7 @@ ${dockerignoreHelp}
|
||||
inlineLogs: composeOpts.inlineLogs,
|
||||
convertEol: composeOpts.convertEol,
|
||||
dockerfilePath: composeOpts.dockerfilePath,
|
||||
nogitignore: composeOpts.nogitignore,
|
||||
nogitignore: composeOpts.nogitignore, // v13: delete this line
|
||||
multiDockerignore: composeOpts.multiDockerignore,
|
||||
});
|
||||
builtImagesByService = _.keyBy(builtImages, 'serviceName');
|
||||
|
@ -47,8 +47,8 @@ interface FlagsDef {
|
||||
pull: boolean;
|
||||
'noparent-check': boolean;
|
||||
'registry-secrets'?: string;
|
||||
gitignore?: boolean;
|
||||
nogitignore?: boolean;
|
||||
gitignore?: boolean; // v13: delete this flag
|
||||
nogitignore?: boolean; // v13: delete this flag
|
||||
nolive: boolean;
|
||||
detached: boolean;
|
||||
service?: string[];
|
||||
@ -237,11 +237,20 @@ export default class PushCmd extends Command {
|
||||
'Have each service use its own .dockerignore file. See "balena help push".',
|
||||
char: 'm',
|
||||
default: false,
|
||||
exclusive: ['gitignore'],
|
||||
exclusive: ['gitignore'], // v13: delete this line
|
||||
}),
|
||||
...(isV13()
|
||||
? {}
|
||||
: {
|
||||
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.`,
|
||||
char: 'g',
|
||||
default: false,
|
||||
exclusive: ['multi-dockerignore'],
|
||||
}),
|
||||
nogitignore: flags.boolean({
|
||||
description:
|
||||
'No-op (default behavior) since balena CLI v12.0.0. See "balena help push".',
|
||||
@ -250,15 +259,6 @@ export default class PushCmd extends Command {
|
||||
default: false,
|
||||
}),
|
||||
}),
|
||||
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.`,
|
||||
char: 'g',
|
||||
default: false,
|
||||
exclusive: ['multi-dockerignore'],
|
||||
}),
|
||||
'release-tag': flags.string({
|
||||
description: stripIndent`
|
||||
Set release tags if the image build is successful (balenaCloud only). Multiple
|
||||
@ -378,7 +378,7 @@ export default class PushCmd extends Command {
|
||||
source: options.source,
|
||||
auth: token,
|
||||
baseUrl,
|
||||
nogitignore: !options.gitignore,
|
||||
nogitignore: !options.gitignore, // v13: delete this line
|
||||
sdk,
|
||||
opts,
|
||||
};
|
||||
@ -422,7 +422,7 @@ export default class PushCmd extends Command {
|
||||
multiDockerignore: options['multi-dockerignore'],
|
||||
nocache: options.nocache,
|
||||
pull: options.pull,
|
||||
nogitignore: !options.gitignore,
|
||||
nogitignore: !options.gitignore, // v13: delete this line
|
||||
noParentCheck: options['noparent-check'],
|
||||
nolive: options.nolive,
|
||||
detached: options.detached,
|
||||
|
8
lib/utils/compose-types.d.ts
vendored
8
lib/utils/compose-types.d.ts
vendored
@ -51,7 +51,7 @@ export interface ComposeOpts {
|
||||
dockerfilePath?: string;
|
||||
inlineLogs?: boolean;
|
||||
multiDockerignore: boolean;
|
||||
nogitignore: boolean;
|
||||
nogitignore: boolean; // v13: delete this line
|
||||
noParentCheck: boolean;
|
||||
projectName: string;
|
||||
projectPath: string;
|
||||
@ -63,9 +63,9 @@ export interface ComposeCliFlags {
|
||||
dockerfile?: string;
|
||||
logs: boolean;
|
||||
nologs: boolean;
|
||||
gitignore: boolean;
|
||||
gitignore?: boolean; // v13: delete this line
|
||||
nogitignore?: boolean; // v13: delete this line
|
||||
'multi-dockerignore': boolean;
|
||||
nogitignore: boolean;
|
||||
'noparent-check': boolean;
|
||||
'registry-secrets'?: RegistrySecrets;
|
||||
'convert-eol': boolean;
|
||||
@ -102,6 +102,6 @@ interface TarDirectoryOptions {
|
||||
composition?: Composition;
|
||||
convertEol?: boolean;
|
||||
multiDockerignore?: boolean;
|
||||
nogitignore: boolean;
|
||||
nogitignore: boolean; // v13: delete this line
|
||||
preFinalizeCallback?: (pack: Pack) => void | Promise<void>;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
import * as path from 'path';
|
||||
import { ExpectedError } from '../errors';
|
||||
import { getChalk } from './lazy';
|
||||
import { isV13 } from './version';
|
||||
|
||||
/**
|
||||
* @returns Promise<{import('./compose-types').ComposeOpts}>
|
||||
@ -25,7 +26,7 @@ import { getChalk } from './lazy';
|
||||
export function generateOpts(options) {
|
||||
const { promises: fs } = require('fs');
|
||||
|
||||
if (options.gitignore && options['multi-dockerignore']) {
|
||||
if (!isV13() && options.gitignore && options['multi-dockerignore']) {
|
||||
throw new ExpectedError(
|
||||
'The --gitignore and --multi-dockerignore options cannot be used together',
|
||||
);
|
||||
@ -37,7 +38,7 @@ export function generateOpts(options) {
|
||||
convertEol: !options['noconvert-eol'],
|
||||
dockerfilePath: options.dockerfile,
|
||||
multiDockerignore: !!options['multi-dockerignore'],
|
||||
nogitignore: !options.gitignore,
|
||||
nogitignore: !options.gitignore, // v13: delete this line
|
||||
noParentCheck: options['noparent-check'],
|
||||
}));
|
||||
}
|
||||
@ -92,6 +93,8 @@ export function createProject(composePath, composeStr, projectName = null) {
|
||||
* @param {string} dir Source directory
|
||||
* @param {import('./compose-types').TarDirectoryOptions} param
|
||||
* @returns {Promise<import('stream').Readable>}
|
||||
*
|
||||
* v13: delete this function
|
||||
*/
|
||||
export async function originalTarDirectory(dir, param) {
|
||||
let {
|
||||
|
@ -18,8 +18,9 @@ import { flags } from '@oclif/command';
|
||||
import { BalenaSDK } from 'balena-sdk';
|
||||
import type { TransposeOptions } from 'docker-qemu-transpose';
|
||||
import type * as Dockerode from 'dockerode';
|
||||
import * as _ from 'lodash';
|
||||
import { promises as fs } from 'fs';
|
||||
import jsyaml = require('js-yaml');
|
||||
import * as _ from 'lodash';
|
||||
import * as path from 'path';
|
||||
import type {
|
||||
BuildConfig,
|
||||
@ -42,8 +43,8 @@ import {
|
||||
import type { DeviceInfo } from './device/api';
|
||||
import { getBalenaSdk, getChalk, stripIndent } from './lazy';
|
||||
import Logger = require('./logger');
|
||||
import { isV13 } from './version';
|
||||
import { exists } from './which';
|
||||
import jsyaml = require('js-yaml');
|
||||
|
||||
const allowedContractTypes = ['sw.application', 'sw.block'];
|
||||
|
||||
@ -250,7 +251,7 @@ export interface BuildProjectOpts {
|
||||
inlineLogs?: boolean;
|
||||
convertEol: boolean;
|
||||
dockerfilePath?: string;
|
||||
nogitignore: boolean;
|
||||
nogitignore: boolean; // v13: delete this line
|
||||
multiDockerignore: boolean;
|
||||
}
|
||||
|
||||
@ -737,8 +738,8 @@ export async function tarDirectory(
|
||||
dir: string,
|
||||
param: TarDirectoryOptions,
|
||||
): Promise<import('stream').Readable> {
|
||||
const { nogitignore = false } = param;
|
||||
if (nogitignore) {
|
||||
const { nogitignore = false } = param; // v13: delete this line
|
||||
if (isV13() || nogitignore) {
|
||||
return newTarDirectory(dir, param);
|
||||
} else {
|
||||
return (await import('./compose')).originalTarDirectory(dir, param);
|
||||
@ -759,11 +760,13 @@ async function newTarDirectory(
|
||||
composition,
|
||||
convertEol = false,
|
||||
multiDockerignore = false,
|
||||
nogitignore = false,
|
||||
nogitignore = false, // v13: delete this line
|
||||
preFinalizeCallback,
|
||||
}: TarDirectoryOptions,
|
||||
): Promise<import('stream').Readable> {
|
||||
require('assert').strict.equal(nogitignore, true);
|
||||
if (!isV13()) {
|
||||
require('assert').strict.equal(nogitignore, true);
|
||||
}
|
||||
const { filterFilesWithDockerignore } = await import('./ignore');
|
||||
const { toPosixPath } = (await import('resin-multibuild')).PathUtils;
|
||||
|
||||
@ -879,7 +882,8 @@ function printDockerignoreWarn(
|
||||
}
|
||||
}
|
||||
if (msg.length) {
|
||||
logFunc.call(logger, [' ', hr, ...msg, hr].join('\n'));
|
||||
const { warnify } = require('./messages') as typeof import('./messages');
|
||||
logFunc.call(logger, ' \n' + warnify(msg.join('\n'), ''));
|
||||
}
|
||||
}
|
||||
|
||||
@ -888,11 +892,16 @@ function printDockerignoreWarn(
|
||||
* found and the --gitignore (-g) option has been provided (v11 compatibility).
|
||||
* @param dockerignoreFile Absolute path to a .dockerignore file
|
||||
* @param gitignoreFiles Array of absolute paths to .gitginore files
|
||||
*
|
||||
* v13: delete this function
|
||||
*/
|
||||
export function printGitignoreWarn(
|
||||
dockerignoreFile: string,
|
||||
gitignoreFiles: string[],
|
||||
) {
|
||||
if (isV13()) {
|
||||
return;
|
||||
}
|
||||
const ignoreFiles = [dockerignoreFile, ...gitignoreFiles].filter((e) => e);
|
||||
if (ignoreFiles.length === 0) {
|
||||
return;
|
||||
@ -1619,22 +1628,26 @@ export const composeCliFlags: flags.Input<ComposeCliFlags> = {
|
||||
description:
|
||||
'Hide the image build log output (produce less verbose output)',
|
||||
}),
|
||||
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.`,
|
||||
char: 'g',
|
||||
}),
|
||||
...(isV13()
|
||||
? {}
|
||||
: {
|
||||
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.`,
|
||||
char: 'g',
|
||||
}),
|
||||
nogitignore: flags.boolean({
|
||||
description: `No-op (default behavior) since balena CLI v12.0.0. See "balena help build".`,
|
||||
char: 'G',
|
||||
}),
|
||||
}),
|
||||
'multi-dockerignore': flags.boolean({
|
||||
description:
|
||||
'Have each service use its own .dockerignore file. See "balena help build".',
|
||||
char: 'm',
|
||||
}),
|
||||
nogitignore: flags.boolean({
|
||||
description: `No-op (default behavior) since balena CLI v12.0.0. See "balena help build".`,
|
||||
char: 'G',
|
||||
}),
|
||||
'noparent-check': flags.boolean({
|
||||
description:
|
||||
"Disable project validation check of 'docker-compose.yml' file in parent folder",
|
||||
|
@ -57,7 +57,7 @@ export interface DeviceDeployOptions {
|
||||
registrySecrets: RegistrySecrets;
|
||||
multiDockerignore: boolean;
|
||||
nocache: boolean;
|
||||
nogitignore: boolean;
|
||||
nogitignore: boolean; // v13: delete this line
|
||||
noParentCheck: boolean;
|
||||
nolive: boolean;
|
||||
pull: boolean;
|
||||
@ -182,7 +182,7 @@ export async function deployToDevice(opts: DeviceDeployOptions): Promise<void> {
|
||||
convertEol: opts.convertEol,
|
||||
dockerfilePath: opts.dockerfilePath,
|
||||
multiDockerignore: opts.multiDockerignore,
|
||||
nogitignore: opts.nogitignore,
|
||||
nogitignore: opts.nogitignore, // v13: delete this line
|
||||
noParentCheck: opts.noParentCheck,
|
||||
projectName: 'local',
|
||||
projectPath: opts.source,
|
||||
@ -201,7 +201,7 @@ export async function deployToDevice(opts: DeviceDeployOptions): Promise<void> {
|
||||
composition: project.composition,
|
||||
convertEol: opts.convertEol,
|
||||
multiDockerignore: opts.multiDockerignore,
|
||||
nogitignore: opts.nogitignore,
|
||||
nogitignore: opts.nogitignore, // v13: delete this line
|
||||
});
|
||||
|
||||
// Try to detect the device information
|
||||
@ -426,7 +426,7 @@ export async function rebuildSingleTask(
|
||||
composition,
|
||||
convertEol: opts.convertEol,
|
||||
multiDockerignore: opts.multiDockerignore,
|
||||
nogitignore: opts.nogitignore,
|
||||
nogitignore: opts.nogitignore, // v13: delete this line
|
||||
});
|
||||
|
||||
const task = _.find(
|
||||
|
@ -27,6 +27,7 @@ import { ExpectedError } from '../errors';
|
||||
|
||||
const { toPosixPath } = MultiBuild.PathUtils;
|
||||
|
||||
// v13: delete this enum
|
||||
export enum IgnoreFileType {
|
||||
DockerIgnore,
|
||||
GitIgnore,
|
||||
@ -42,6 +43,8 @@ interface IgnoreEntry {
|
||||
* This class is used by the CLI v10 / v11 "original" tarDirectory function
|
||||
* in `compose.js`. It is still around for the benefit of the `--gitignore`
|
||||
* option, but is expected to be deleted in CLI v13.
|
||||
*
|
||||
* v13: delete this class
|
||||
*/
|
||||
export class FileIgnorer {
|
||||
private dockerIgnoreEntries: IgnoreEntry[];
|
||||
|
@ -15,6 +15,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { isV13 } from './version';
|
||||
|
||||
export const reachingOut = `\
|
||||
For further help or support, visit:
|
||||
https://www.balena.io/docs/reference/balena-cli/#support-faq-and-troubleshooting
|
||||
@ -48,7 +50,8 @@ used. Find out more at: https://git.io/JRHUW#deprecation-policy
|
||||
* where the length of the dash rows matches the length of the longest line.
|
||||
*/
|
||||
export function warnify(msg: string, prefix = '[Warn] ') {
|
||||
const lines = msg.split('\n').map((l) => `${prefix}${l}`);
|
||||
let lines = msg.split('\n');
|
||||
lines = prefix ? lines.map((l) => `${prefix}${l}`) : lines;
|
||||
const maxLength = Math.max(...lines.map((l) => l.length));
|
||||
const hr = '-'.repeat(maxLength);
|
||||
return [hr, ...lines, hr].join('\n');
|
||||
@ -85,7 +88,7 @@ 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.`;
|
||||
|
||||
export const dockerignoreHelp =
|
||||
const dockerignoreHelpV12 =
|
||||
'DOCKERIGNORE AND GITIGNORE FILES \n' +
|
||||
`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
|
||||
@ -138,6 +141,60 @@ adding counter patterns to the applicable .dockerignore file(s), for example
|
||||
- https://docs.docker.com/engine/reference/builder/#dockerignore-file
|
||||
- https://www.npmjs.com/package/@balena/dockerignore`;
|
||||
|
||||
const dockerignoreHelpV13 =
|
||||
'DOCKERIGNORE AND GITIGNORE FILES \n' +
|
||||
`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
|
||||
daemon or balenaEngine. In a microservices (multicontainer) fleet, the
|
||||
source directory is the directory that contains the "docker-compose.yml" file.
|
||||
|
||||
The --multi-dockerignore (-m) option may be used with microservices
|
||||
(multicontainer) fleets that define a docker-compose.yml file. When this
|
||||
option is used, each service subdirectory (defined by the \`build\` or
|
||||
\`build.context\` service properties in the docker-compose.yml file) is
|
||||
filtered separately according to a .dockerignore file defined in the service
|
||||
subdirectory. If no .dockerignore file exists in a service subdirectory, then
|
||||
only the default .dockerignore patterns (see below) apply for that service
|
||||
subdirectory.
|
||||
|
||||
When the --multi-dockerignore (-m) option is used, the .dockerignore file (if
|
||||
any) defined at the overall project root will be used to filter files and
|
||||
subdirectories other than service subdirectories. It will not have any effect
|
||||
on service subdirectories, whether or not a service subdirectory defines its
|
||||
own .dockerignore file. Multiple .dockerignore files are not merged or added
|
||||
together, and cannot override or extend other files. This behavior maximizes
|
||||
compatibility with the standard docker-compose tool, while still allowing a
|
||||
root .dockerignore file (at the overall project root) to filter files and
|
||||
folders that are outside service subdirectories.
|
||||
|
||||
balena CLI v11 also took .gitignore files into account. This behavior was
|
||||
deprecated in CLI v12 and removed in CLI v13. Please use .dockerignore files
|
||||
instead.
|
||||
|
||||
Default .dockerignore patterns \n` +
|
||||
`A few default/hardcoded dockerignore patterns are "merged" (in memory) with the
|
||||
patterns found in the applicable .dockerignore files, in the following order:
|
||||
\`\`\`
|
||||
**/.git
|
||||
< user's patterns from the applicable '.dockerignore' file, if any >
|
||||
!**/.balena
|
||||
!**/.resin
|
||||
!**/Dockerfile
|
||||
!**/Dockerfile.*
|
||||
!**/docker-compose.yml
|
||||
\`\`\`
|
||||
These patterns always apply, whether or not .dockerignore files exist in the
|
||||
project. If necessary, the effect of the \`**/.git\` pattern may be modified by
|
||||
adding exception 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`;
|
||||
|
||||
export const dockerignoreHelp = isV13()
|
||||
? dockerignoreHelpV13
|
||||
: dockerignoreHelpV12;
|
||||
|
||||
export const applicationIdInfo = `\
|
||||
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
|
||||
the recommended option, as they are unique and unambiguous. Slugs can be
|
||||
|
@ -50,7 +50,7 @@ export interface RemoteBuild {
|
||||
source: string;
|
||||
auth: string;
|
||||
baseUrl: string;
|
||||
nogitignore: boolean;
|
||||
nogitignore: boolean; // v13: delete this line
|
||||
opts: BuildOpts;
|
||||
sdk: BalenaSDK;
|
||||
// For internal use
|
||||
@ -321,7 +321,7 @@ async function getTarStream(build: RemoteBuild): Promise<Stream.Readable> {
|
||||
preFinalizeCallback: preFinalizeCb,
|
||||
convertEol: build.opts.convertEol,
|
||||
multiDockerignore: build.opts.multiDockerignore,
|
||||
nogitignore: build.nogitignore,
|
||||
nogitignore: build.nogitignore, // v13: delete this line
|
||||
});
|
||||
} finally {
|
||||
tarSpinner.stop();
|
||||
|
@ -21,7 +21,8 @@ import mock = require('mock-require');
|
||||
import { promises as fs } from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
import { stripIndent } from '../../lib/utils/lazy';
|
||||
import { stripIndent } from '../../build/utils/lazy';
|
||||
import { isV13 } from '../../build/utils/version';
|
||||
import { BalenaAPIMock } from '../nock/balena-api-mock';
|
||||
import { expectStreamNoCRLF, testDockerBuildStream } from '../docker-build';
|
||||
import { DockerMock, dockerResponsePath } from '../nock/docker-mock';
|
||||
@ -61,9 +62,6 @@ const commonComposeQueryParams = {
|
||||
labels: '',
|
||||
};
|
||||
|
||||
const hr =
|
||||
'----------------------------------------------------------------------';
|
||||
|
||||
// "itSS" means "it() Skip Standalone"
|
||||
const itSS = process.env.BALENA_CLI_TEST_TYPE === 'standalone' ? it.skip : it;
|
||||
|
||||
@ -126,7 +124,9 @@ describe('balena build', function () {
|
||||
}
|
||||
docker.expectGetInfo({});
|
||||
await testDockerBuildStream({
|
||||
commandLine: `build ${projectPath} --deviceType nuc --arch amd64 -g`,
|
||||
commandLine: `build ${projectPath} --deviceType nuc --arch amd64 ${
|
||||
isV13() ? '' : '-g'
|
||||
}`,
|
||||
dockerMock: docker,
|
||||
expectedFilesByService: { main: expectedFiles },
|
||||
expectedQueryParamsByService: { main: Object.entries(commonQueryParams) },
|
||||
@ -272,7 +272,9 @@ describe('balena build', function () {
|
||||
mock.reRequire('../../build/utils/qemu');
|
||||
docker.expectGetInfo({ OperatingSystem: 'balenaOS 2.44.0+rev1' });
|
||||
await testDockerBuildStream({
|
||||
commandLine: `build ${projectPath} --emulated --deviceType ${deviceType} --arch ${arch} --nogitignore`,
|
||||
commandLine: `build ${projectPath} --emulated --deviceType ${deviceType} --arch ${arch} ${
|
||||
isV13() ? '' : '--nogitignore'
|
||||
}`,
|
||||
dockerMock: docker,
|
||||
expectedFilesByService: { main: expectedFiles },
|
||||
expectedQueryParamsByService: {
|
||||
@ -416,7 +418,9 @@ describe('balena build', function () {
|
||||
}
|
||||
docker.expectGetInfo({});
|
||||
await testDockerBuildStream({
|
||||
commandLine: `build ${projectPath} --deviceType nuc --arch amd64 --convert-eol -G -B COMPOSE_ARG=A -B barg=b --cache-from my/img1,my/img2`,
|
||||
commandLine: `build ${projectPath} --deviceType nuc --arch amd64 --convert-eol ${
|
||||
isV13() ? '' : '-G'
|
||||
} -B COMPOSE_ARG=A -B barg=b --cache-from my/img1,my/img2`,
|
||||
dockerMock: docker,
|
||||
expectedFilesByService,
|
||||
expectedQueryParamsByService,
|
||||
@ -484,11 +488,11 @@ describe('balena build', function () {
|
||||
'[Build] service2 Step 1/4 : FROM busybox',
|
||||
],
|
||||
...[
|
||||
`[Info] ${hr}`,
|
||||
`[Info] ---------------------------------------------------------------------------`,
|
||||
'[Info] The --multi-dockerignore option is being used, and a .dockerignore file was',
|
||||
'[Info] found at the project source (root) directory. Note that this file will not',
|
||||
'[Info] be used to filter service subdirectories. See "balena help build".',
|
||||
`[Info] ${hr}`,
|
||||
`[Info] ---------------------------------------------------------------------------`,
|
||||
],
|
||||
];
|
||||
if (isWindows) {
|
||||
|
@ -23,6 +23,7 @@ import * as nock from 'nock';
|
||||
import * as path from 'path';
|
||||
import * as sinon from 'sinon';
|
||||
|
||||
import { isV13 } from '../../build/utils/version';
|
||||
import { BalenaAPIMock } from '../nock/balena-api-mock';
|
||||
import { expectStreamNoCRLF, testDockerBuildStream } from '../docker-build';
|
||||
import { DockerMock, dockerResponsePath } from '../nock/docker-mock';
|
||||
@ -66,9 +67,6 @@ const commonComposeQueryParams = {
|
||||
labels: '',
|
||||
};
|
||||
|
||||
const hr =
|
||||
'----------------------------------------------------------------------';
|
||||
|
||||
describe('balena deploy', function () {
|
||||
let api: BalenaAPIMock;
|
||||
let docker: DockerMock;
|
||||
@ -143,7 +141,9 @@ describe('balena deploy', function () {
|
||||
api.expectPostImageLabel();
|
||||
|
||||
await testDockerBuildStream({
|
||||
commandLine: `deploy testApp --build --source ${projectPath} -G`,
|
||||
commandLine: `deploy testApp --build --source ${projectPath} ${
|
||||
isV13() ? '' : '-G'
|
||||
}`,
|
||||
dockerMock: docker,
|
||||
expectedFilesByService: { main: expectedFiles },
|
||||
expectedQueryParamsByService: { main: commonQueryParams },
|
||||
@ -304,7 +304,9 @@ describe('balena deploy', function () {
|
||||
sinon.stub(process, 'exit');
|
||||
|
||||
await testDockerBuildStream({
|
||||
commandLine: `deploy testApp --build --source ${projectPath} --noconvert-eol -G`,
|
||||
commandLine: `deploy testApp --build --source ${projectPath} --noconvert-eol ${
|
||||
isV13() ? '' : '-G'
|
||||
}`,
|
||||
dockerMock: docker,
|
||||
expectedFilesByService: { main: expectedFiles },
|
||||
expectedQueryParamsByService: { main: commonQueryParams },
|
||||
@ -385,11 +387,11 @@ describe('balena deploy', function () {
|
||||
'[Build] service2 Step 1/4 : FROM busybox',
|
||||
],
|
||||
...[
|
||||
`[Info] ${hr}`,
|
||||
`[Info] ---------------------------------------------------------------------------`,
|
||||
'[Info] The --multi-dockerignore option is being used, and a .dockerignore file was',
|
||||
'[Info] found at the project source (root) directory. Note that this file will not',
|
||||
'[Info] be used to filter service subdirectories. See "balena help deploy".',
|
||||
`[Info] ${hr}`,
|
||||
`[Info] ---------------------------------------------------------------------------`,
|
||||
],
|
||||
];
|
||||
if (isWindows) {
|
||||
|
@ -19,6 +19,7 @@ import { expect } from 'chai';
|
||||
import { promises as fs } from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
import { isV13 } from '../../build/utils/version';
|
||||
import { BalenaAPIMock } from '../nock/balena-api-mock';
|
||||
import { BuilderMock, builderResponsePath } from '../nock/builder-mock';
|
||||
import { expectStreamNoCRLF, testPushBuildStream } from '../docker-build';
|
||||
@ -34,6 +35,8 @@ import {
|
||||
const repoPath = path.normalize(path.join(__dirname, '..', '..'));
|
||||
const projectsPath = path.join(repoPath, 'tests', 'test-data', 'projects');
|
||||
|
||||
const itNoV13 = isV13() ? it.skip : it;
|
||||
|
||||
const commonResponseLines = {
|
||||
'build-POST-v3.json': [
|
||||
'[Info] Starting build for testApp, user gh_user',
|
||||
@ -234,71 +237,74 @@ describe('balena push', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('should create the expected tar stream (single container, --gitignore)', async () => {
|
||||
const projectPath = path.join(
|
||||
projectsPath,
|
||||
'no-docker-compose',
|
||||
'dockerignore1',
|
||||
);
|
||||
const expectedFiles: ExpectedTarStreamFiles = {
|
||||
'.balena/balena.yml': { fileSize: 12, type: 'file' },
|
||||
'.dockerignore': { fileSize: 438, type: 'file' },
|
||||
'.gitignore': { fileSize: 20, type: 'file' },
|
||||
'.git/bar.txt': { fileSize: 4, type: 'file' },
|
||||
'.git/foo.txt': { fileSize: 4, type: 'file' },
|
||||
'c.txt': { fileSize: 1, type: 'file' },
|
||||
Dockerfile: { fileSize: 13, type: 'file' },
|
||||
'src/.balena/balena.yml': { fileSize: 16, type: 'file' },
|
||||
'src/.gitignore': { fileSize: 10, type: 'file' },
|
||||
'vendor/.git/vendor-git-contents': { fileSize: 20, type: 'file' },
|
||||
// When --gitignore (-g) is provided for v11 compatibility, the old
|
||||
// `zeit/dockerignore` npm package is still used but it is broken on
|
||||
// Windows (reason why we created `@balena/dockerignore`).
|
||||
...(isWindows
|
||||
? {
|
||||
'src/src-b.txt': { fileSize: 5, type: 'file' },
|
||||
'dot.git/bar.txt': { fileSize: 4, type: 'file' },
|
||||
'dot.git/foo.txt': { fileSize: 4, type: 'file' },
|
||||
'vendor/dot.git/vendor-git-contents': {
|
||||
fileSize: 20,
|
||||
type: 'file',
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
};
|
||||
itNoV13(
|
||||
'should create the expected tar stream (single container, --gitignore)',
|
||||
async () => {
|
||||
const projectPath = path.join(
|
||||
projectsPath,
|
||||
'no-docker-compose',
|
||||
'dockerignore1',
|
||||
);
|
||||
const expectedFiles: ExpectedTarStreamFiles = {
|
||||
'.balena/balena.yml': { fileSize: 12, type: 'file' },
|
||||
'.dockerignore': { fileSize: 438, type: 'file' },
|
||||
'.gitignore': { fileSize: 20, type: 'file' },
|
||||
'.git/bar.txt': { fileSize: 4, type: 'file' },
|
||||
'.git/foo.txt': { fileSize: 4, type: 'file' },
|
||||
'c.txt': { fileSize: 1, type: 'file' },
|
||||
Dockerfile: { fileSize: 13, type: 'file' },
|
||||
'src/.balena/balena.yml': { fileSize: 16, type: 'file' },
|
||||
'src/.gitignore': { fileSize: 10, type: 'file' },
|
||||
'vendor/.git/vendor-git-contents': { fileSize: 20, type: 'file' },
|
||||
// When --gitignore (-g) is provided for v11 compatibility, the old
|
||||
// `zeit/dockerignore` npm package is still used but it is broken on
|
||||
// Windows (reason why we created `@balena/dockerignore`).
|
||||
...(isWindows
|
||||
? {
|
||||
'src/src-b.txt': { fileSize: 5, type: 'file' },
|
||||
'dot.git/bar.txt': { fileSize: 4, type: 'file' },
|
||||
'dot.git/foo.txt': { fileSize: 4, type: 'file' },
|
||||
'vendor/dot.git/vendor-git-contents': {
|
||||
fileSize: 20,
|
||||
type: 'file',
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
};
|
||||
|
||||
const regSecretsPath = await addRegSecretsEntries(expectedFiles);
|
||||
const responseFilename = 'build-POST-v3.json';
|
||||
const responseBody = await fs.readFile(
|
||||
path.join(builderResponsePath, responseFilename),
|
||||
'utf8',
|
||||
);
|
||||
const expectedResponseLines = [
|
||||
...[
|
||||
`[Warn] ${hr}`,
|
||||
'[Warn] Using file ignore patterns from:',
|
||||
`[Warn] * ${path.join(projectPath, '.dockerignore')}`,
|
||||
`[Warn] * ${path.join(projectPath, '.gitignore')}`,
|
||||
`[Warn] * ${path.join(projectPath, 'src', '.gitignore')}`,
|
||||
'[Warn] .gitignore files are being considered because the --gitignore option was used.',
|
||||
'[Warn] This option is deprecated and will be removed in the next major version release.',
|
||||
"[Warn] For more information, see 'balena help push'.",
|
||||
`[Warn] ${hr}`,
|
||||
],
|
||||
...commonResponseLines[responseFilename],
|
||||
];
|
||||
const regSecretsPath = await addRegSecretsEntries(expectedFiles);
|
||||
const responseFilename = 'build-POST-v3.json';
|
||||
const responseBody = await fs.readFile(
|
||||
path.join(builderResponsePath, responseFilename),
|
||||
'utf8',
|
||||
);
|
||||
const expectedResponseLines = [
|
||||
...[
|
||||
`[Warn] ${hr}`,
|
||||
'[Warn] Using file ignore patterns from:',
|
||||
`[Warn] * ${path.join(projectPath, '.dockerignore')}`,
|
||||
`[Warn] * ${path.join(projectPath, '.gitignore')}`,
|
||||
`[Warn] * ${path.join(projectPath, 'src', '.gitignore')}`,
|
||||
'[Warn] .gitignore files are being considered because the --gitignore option was used.',
|
||||
'[Warn] This option is deprecated and will be removed in the next major version release.',
|
||||
"[Warn] For more information, see 'balena help push'.",
|
||||
`[Warn] ${hr}`,
|
||||
],
|
||||
...commonResponseLines[responseFilename],
|
||||
];
|
||||
|
||||
await testPushBuildStream({
|
||||
builderMock: builder,
|
||||
commandLine: `push testApp -s ${projectPath} -R ${regSecretsPath} -g`,
|
||||
expectedFiles,
|
||||
expectedQueryParams: commonQueryParams,
|
||||
expectedResponseLines,
|
||||
projectPath,
|
||||
responseBody,
|
||||
responseCode: 200,
|
||||
});
|
||||
});
|
||||
await testPushBuildStream({
|
||||
builderMock: builder,
|
||||
commandLine: `push testApp -s ${projectPath} -R ${regSecretsPath} -g`,
|
||||
expectedFiles,
|
||||
expectedQueryParams: commonQueryParams,
|
||||
expectedResponseLines,
|
||||
projectPath,
|
||||
responseBody,
|
||||
responseCode: 200,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it('should create the expected tar stream (single container, --nogitignore)', async () => {
|
||||
const projectPath = path.join(
|
||||
@ -370,24 +376,27 @@ describe('balena push', function () {
|
||||
path.join(builderResponsePath, responseFilename),
|
||||
'utf8',
|
||||
);
|
||||
const expectedResponseLines = isWindows
|
||||
? [
|
||||
`[Warn] ${hr}`,
|
||||
'[Warn] Using file ignore patterns from:',
|
||||
`[Warn] * ${path.join(projectPath, '.dockerignore')}`,
|
||||
'[Warn] The --gitignore option was used, but no .gitignore files were found.',
|
||||
'[Warn] The --gitignore option is deprecated and will be removed in the next major',
|
||||
'[Warn] version release. It prevents the use of a better dockerignore parser and',
|
||||
'[Warn] filter library that fixes several issues on Windows and improves compatibility',
|
||||
"[Warn] with 'docker build'. For more information, see 'balena help push'.",
|
||||
`[Warn] ${hr}`,
|
||||
...commonResponseLines[responseFilename],
|
||||
]
|
||||
: commonResponseLines[responseFilename];
|
||||
const expectedResponseLines =
|
||||
!isV13() && isWindows
|
||||
? [
|
||||
`[Warn] ${hr}`,
|
||||
'[Warn] Using file ignore patterns from:',
|
||||
`[Warn] * ${path.join(projectPath, '.dockerignore')}`,
|
||||
'[Warn] The --gitignore option was used, but no .gitignore files were found.',
|
||||
'[Warn] The --gitignore option is deprecated and will be removed in the next major',
|
||||
'[Warn] version release. It prevents the use of a better dockerignore parser and',
|
||||
'[Warn] filter library that fixes several issues on Windows and improves compatibility',
|
||||
"[Warn] with 'docker build'. For more information, see 'balena help push'.",
|
||||
`[Warn] ${hr}`,
|
||||
...commonResponseLines[responseFilename],
|
||||
]
|
||||
: commonResponseLines[responseFilename];
|
||||
|
||||
await testPushBuildStream({
|
||||
builderMock: builder,
|
||||
commandLine: `push testApp -s ${projectPath} -R ${regSecretsPath} --gitignore`,
|
||||
commandLine: `push testApp -s ${projectPath} -R ${regSecretsPath} ${
|
||||
isV13() ? '' : '--gitignore'
|
||||
}`,
|
||||
expectedFiles,
|
||||
expectedQueryParams: commonQueryParams,
|
||||
expectedResponseLines,
|
||||
@ -516,11 +525,11 @@ describe('balena push', function () {
|
||||
const expectedResponseLines: string[] = [
|
||||
...commonResponseLines[responseFilename],
|
||||
...[
|
||||
`[Info] ${hr}`,
|
||||
`[Info] ---------------------------------------------------------------------------`,
|
||||
'[Info] The --multi-dockerignore option is being used, and a .dockerignore file was',
|
||||
'[Info] found at the project source (root) directory. Note that this file will not',
|
||||
'[Info] be used to filter service subdirectories. See "balena help push".',
|
||||
`[Info] ${hr}`,
|
||||
`[Info] ---------------------------------------------------------------------------`,
|
||||
],
|
||||
];
|
||||
if (isWindows) {
|
||||
@ -571,7 +580,7 @@ describe('balena push: project validation', function () {
|
||||
];
|
||||
|
||||
const { out, err } = await runCommand(
|
||||
`push testApp --source ${projectPath} --gitignore`,
|
||||
`push testApp --source ${projectPath}`,
|
||||
);
|
||||
expect(cleanOutput(err, true)).to.include.members(expectedErrorLines);
|
||||
expect(out).to.be.empty;
|
||||
|
@ -105,7 +105,7 @@ async function runCommandInProcess(cmd: string): Promise<TestOutput> {
|
||||
const unhookIntercept = intercept(stdoutHook, stderrHook);
|
||||
|
||||
try {
|
||||
await balenaCLI.run(preArgs.concat(cmd.split(' ')), {
|
||||
await balenaCLI.run(preArgs.concat(cmd.split(' ').filter((c) => c)), {
|
||||
noFlush: true,
|
||||
});
|
||||
} finally {
|
||||
@ -160,7 +160,7 @@ async function runCommandInSubprocess(
|
||||
await new Promise<void>((resolve) => {
|
||||
const child = execFile(
|
||||
standalonePath,
|
||||
cmd.split(' '),
|
||||
cmd.split(' ').filter((c) => c),
|
||||
{ env: { ...process.env, ...addedEnvs } },
|
||||
($error, $stdout, $stderr) => {
|
||||
stderr = $stderr || '';
|
||||
|
@ -86,7 +86,6 @@ export async function addRegSecretsEntries(
|
||||
|
||||
export function getDockerignoreWarn1(paths: string[], cmd: string) {
|
||||
const lines = [
|
||||
'[Warn] ----------------------------------------------------------------------',
|
||||
'[Warn] The following .dockerignore file(s) will not be used:',
|
||||
];
|
||||
lines.push(...paths.map((p) => `[Warn] * ${p}`));
|
||||
@ -96,7 +95,6 @@ export function getDockerignoreWarn1(paths: string[], cmd: string) {
|
||||
'[Warn] root) is used. Microservices (multicontainer) fleets may use a separate',
|
||||
'[Warn] .dockerignore file for each service with the --multi-dockerignore (-m)',
|
||||
`[Warn] option. See "balena help ${cmd}" for more details.`,
|
||||
'[Warn] ----------------------------------------------------------------------',
|
||||
],
|
||||
);
|
||||
return lines;
|
||||
@ -104,7 +102,6 @@ export function getDockerignoreWarn1(paths: string[], cmd: string) {
|
||||
|
||||
export function getDockerignoreWarn2(paths: string[], cmd: string) {
|
||||
const lines = [
|
||||
'[Warn] ----------------------------------------------------------------------',
|
||||
'[Warn] The following .dockerignore file(s) will not be used:',
|
||||
];
|
||||
lines.push(...paths.map((p) => `[Warn] * ${p}`));
|
||||
@ -114,7 +111,6 @@ export function getDockerignoreWarn2(paths: string[], cmd: string) {
|
||||
"[Warn] root of each service's build context (in a microservices/multicontainer",
|
||||
'[Warn] fleet), plus a .dockerignore file at the overall project root, are used.',
|
||||
`[Warn] See "balena help ${cmd}" for more details.`,
|
||||
'[Warn] ----------------------------------------------------------------------',
|
||||
],
|
||||
);
|
||||
return lines;
|
||||
|
@ -7,6 +7,9 @@ import { FileIgnorer, IgnoreFileType } from '../../build/utils/ignore';
|
||||
// of the FileIgnorer class to prevent a Typescript compilation error (this
|
||||
// behavior is by design: see
|
||||
// https://github.com/microsoft/TypeScript/issues/19335 )
|
||||
//
|
||||
// v13: delete this file
|
||||
//
|
||||
describe('File ignorer', function () {
|
||||
it('should detect ignore files', function () {
|
||||
const f = new FileIgnorer(`.${path.sep}`);
|
||||
|
Loading…
x
Reference in New Issue
Block a user