mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-02-21 09:51:58 +00:00
build/deploy/push: Remove deprecated '--[no]gitignore' option
Change-type: major
This commit is contained in:
parent
23b42b1a2b
commit
73572df7cf
@ -271,7 +271,6 @@ ${dockerignoreHelp}
|
|||||||
inlineLogs: composeOpts.inlineLogs,
|
inlineLogs: composeOpts.inlineLogs,
|
||||||
convertEol: composeOpts.convertEol,
|
convertEol: composeOpts.convertEol,
|
||||||
dockerfilePath: composeOpts.dockerfilePath,
|
dockerfilePath: composeOpts.dockerfilePath,
|
||||||
nogitignore: composeOpts.nogitignore, // v13: delete this line
|
|
||||||
multiDockerignore: composeOpts.multiDockerignore,
|
multiDockerignore: composeOpts.multiDockerignore,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -319,7 +319,6 @@ ${dockerignoreHelp}
|
|||||||
inlineLogs: composeOpts.inlineLogs,
|
inlineLogs: composeOpts.inlineLogs,
|
||||||
convertEol: composeOpts.convertEol,
|
convertEol: composeOpts.convertEol,
|
||||||
dockerfilePath: composeOpts.dockerfilePath,
|
dockerfilePath: composeOpts.dockerfilePath,
|
||||||
nogitignore: composeOpts.nogitignore, // v13: delete this line
|
|
||||||
multiDockerignore: composeOpts.multiDockerignore,
|
multiDockerignore: composeOpts.multiDockerignore,
|
||||||
});
|
});
|
||||||
builtImagesByService = _.keyBy(builtImages, 'serviceName');
|
builtImagesByService = _.keyBy(builtImages, 'serviceName');
|
||||||
|
@ -47,8 +47,6 @@ interface FlagsDef {
|
|||||||
pull: boolean;
|
pull: boolean;
|
||||||
'noparent-check': boolean;
|
'noparent-check': boolean;
|
||||||
'registry-secrets'?: string;
|
'registry-secrets'?: string;
|
||||||
gitignore?: boolean; // v13: delete this flag
|
|
||||||
nogitignore?: boolean; // v13: delete this flag
|
|
||||||
nolive: boolean;
|
nolive: boolean;
|
||||||
detached: boolean;
|
detached: boolean;
|
||||||
service?: string[];
|
service?: string[];
|
||||||
@ -237,28 +235,7 @@ export default class PushCmd extends Command {
|
|||||||
'Have each service use its own .dockerignore file. See "balena help push".',
|
'Have each service use its own .dockerignore file. See "balena help push".',
|
||||||
char: 'm',
|
char: 'm',
|
||||||
default: false,
|
default: false,
|
||||||
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".',
|
|
||||||
char: 'G',
|
|
||||||
hidden: true,
|
|
||||||
default: false,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
'release-tag': flags.string({
|
'release-tag': flags.string({
|
||||||
description: stripIndent`
|
description: stripIndent`
|
||||||
Set release tags if the image build is successful (balenaCloud only). Multiple
|
Set release tags if the image build is successful (balenaCloud only). Multiple
|
||||||
@ -378,7 +355,6 @@ export default class PushCmd extends Command {
|
|||||||
source: options.source,
|
source: options.source,
|
||||||
auth: token,
|
auth: token,
|
||||||
baseUrl,
|
baseUrl,
|
||||||
nogitignore: !options.gitignore, // v13: delete this line
|
|
||||||
sdk,
|
sdk,
|
||||||
opts,
|
opts,
|
||||||
};
|
};
|
||||||
@ -422,7 +398,6 @@ export default class PushCmd extends Command {
|
|||||||
multiDockerignore: options['multi-dockerignore'],
|
multiDockerignore: options['multi-dockerignore'],
|
||||||
nocache: options.nocache,
|
nocache: options.nocache,
|
||||||
pull: options.pull,
|
pull: options.pull,
|
||||||
nogitignore: !options.gitignore, // v13: delete this line
|
|
||||||
noParentCheck: options['noparent-check'],
|
noParentCheck: options['noparent-check'],
|
||||||
nolive: options.nolive,
|
nolive: options.nolive,
|
||||||
detached: options.detached,
|
detached: options.detached,
|
||||||
|
4
lib/utils/compose-types.d.ts
vendored
4
lib/utils/compose-types.d.ts
vendored
@ -51,7 +51,6 @@ export interface ComposeOpts {
|
|||||||
dockerfilePath?: string;
|
dockerfilePath?: string;
|
||||||
inlineLogs?: boolean;
|
inlineLogs?: boolean;
|
||||||
multiDockerignore: boolean;
|
multiDockerignore: boolean;
|
||||||
nogitignore: boolean; // v13: delete this line
|
|
||||||
noParentCheck: boolean;
|
noParentCheck: boolean;
|
||||||
projectName: string;
|
projectName: string;
|
||||||
projectPath: string;
|
projectPath: string;
|
||||||
@ -63,8 +62,6 @@ export interface ComposeCliFlags {
|
|||||||
dockerfile?: string;
|
dockerfile?: string;
|
||||||
logs: boolean;
|
logs: boolean;
|
||||||
nologs: boolean;
|
nologs: boolean;
|
||||||
gitignore?: boolean; // v13: delete this line
|
|
||||||
nogitignore?: boolean; // v13: delete this line
|
|
||||||
'multi-dockerignore': boolean;
|
'multi-dockerignore': boolean;
|
||||||
'noparent-check': boolean;
|
'noparent-check': boolean;
|
||||||
'registry-secrets'?: RegistrySecrets;
|
'registry-secrets'?: RegistrySecrets;
|
||||||
@ -102,6 +99,5 @@ interface TarDirectoryOptions {
|
|||||||
composition?: Composition;
|
composition?: Composition;
|
||||||
convertEol?: boolean;
|
convertEol?: boolean;
|
||||||
multiDockerignore?: boolean;
|
multiDockerignore?: boolean;
|
||||||
nogitignore: boolean; // v13: delete this line
|
|
||||||
preFinalizeCallback?: (pack: Pack) => void | Promise<void>;
|
preFinalizeCallback?: (pack: Pack) => void | Promise<void>;
|
||||||
}
|
}
|
||||||
|
@ -16,21 +16,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { ExpectedError } from '../errors';
|
|
||||||
import { getChalk } from './lazy';
|
import { getChalk } from './lazy';
|
||||||
import { isV13 } from './version';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns Promise<{import('./compose-types').ComposeOpts}>
|
* @returns Promise<{import('./compose-types').ComposeOpts}>
|
||||||
*/
|
*/
|
||||||
export function generateOpts(options) {
|
export function generateOpts(options) {
|
||||||
const { promises: fs } = require('fs');
|
const { promises: fs } = require('fs');
|
||||||
|
|
||||||
if (!isV13() && options.gitignore && options['multi-dockerignore']) {
|
|
||||||
throw new ExpectedError(
|
|
||||||
'The --gitignore and --multi-dockerignore options cannot be used together',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return fs.realpath(options.source || '.').then((projectPath) => ({
|
return fs.realpath(options.source || '.').then((projectPath) => ({
|
||||||
projectName: options.projectName,
|
projectName: options.projectName,
|
||||||
projectPath,
|
projectPath,
|
||||||
@ -38,7 +30,6 @@ 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'],
|
||||||
nogitignore: !options.gitignore, // v13: delete this line
|
|
||||||
noParentCheck: options['noparent-check'],
|
noParentCheck: options['noparent-check'],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -89,92 +80,6 @@ export function createProject(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the CLI v10 / v11 "original" tarDirectory function. It is still
|
|
||||||
* around for the benefit of the `--gitignore` option, but is expected to be
|
|
||||||
* deleted in CLI v13.
|
|
||||||
* @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 {
|
|
||||||
preFinalizeCallback = null,
|
|
||||||
convertEol = false,
|
|
||||||
nogitignore = false,
|
|
||||||
} = param;
|
|
||||||
if (convertEol == null) {
|
|
||||||
convertEol = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Bluebird = require('bluebird');
|
|
||||||
const tar = require('tar-stream');
|
|
||||||
const klaw = require('klaw');
|
|
||||||
const { promises: fs } = require('fs');
|
|
||||||
const streamToPromise = require('stream-to-promise');
|
|
||||||
const { printGitignoreWarn } = require('./compose_ts');
|
|
||||||
const { FileIgnorer, IgnoreFileType } = require('./ignore');
|
|
||||||
const { toPosixPath } = require('resin-multibuild').PathUtils;
|
|
||||||
let readFile;
|
|
||||||
if (process.platform === 'win32') {
|
|
||||||
const { readFileWithEolConversion } = require('./eol-conversion');
|
|
||||||
readFile = (file) => readFileWithEolConversion(file, convertEol);
|
|
||||||
} else {
|
|
||||||
({ readFile } = fs);
|
|
||||||
}
|
|
||||||
|
|
||||||
const getFiles = () =>
|
|
||||||
Bluebird.resolve(streamToPromise(klaw(dir)))
|
|
||||||
// @ts-ignore
|
|
||||||
.filter((item) => !item.stats.isDirectory())
|
|
||||||
// @ts-ignore
|
|
||||||
.map((item) => item.path);
|
|
||||||
|
|
||||||
const ignore = new FileIgnorer(dir);
|
|
||||||
const pack = tar.pack();
|
|
||||||
const ignoreFiles = {};
|
|
||||||
return getFiles()
|
|
||||||
.each(function (file) {
|
|
||||||
const type = ignore.getIgnoreFileType(path.relative(dir, file));
|
|
||||||
if (type != null) {
|
|
||||||
ignoreFiles[type] = ignoreFiles[type] || [];
|
|
||||||
ignoreFiles[type].push(path.resolve(dir, file));
|
|
||||||
return ignore.addIgnoreFile(file, type);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.tap(() => {
|
|
||||||
if (!nogitignore) {
|
|
||||||
printGitignoreWarn(
|
|
||||||
(ignoreFiles[IgnoreFileType.DockerIgnore] || [])[0] || '',
|
|
||||||
ignoreFiles[IgnoreFileType.GitIgnore] || [],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.filter(ignore.filter)
|
|
||||||
.map(function (file) {
|
|
||||||
const relPath = path.relative(path.resolve(dir), file);
|
|
||||||
return Promise.all([relPath, fs.stat(file), readFile(file)]).then(
|
|
||||||
([filename, stats, data]) =>
|
|
||||||
pack.entry(
|
|
||||||
{
|
|
||||||
name: toPosixPath(filename),
|
|
||||||
mtime: stats.mtime,
|
|
||||||
size: stats.size,
|
|
||||||
mode: stats.mode,
|
|
||||||
},
|
|
||||||
data,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.then(() => preFinalizeCallback?.(pack))
|
|
||||||
.then(function () {
|
|
||||||
pack.finalize();
|
|
||||||
return pack;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} apiEndpoint
|
* @param {string} apiEndpoint
|
||||||
* @param {string} auth
|
* @param {string} auth
|
||||||
|
@ -43,7 +43,6 @@ import {
|
|||||||
import type { DeviceInfo } from './device/api';
|
import type { DeviceInfo } from './device/api';
|
||||||
import { getBalenaSdk, getChalk, stripIndent } from './lazy';
|
import { getBalenaSdk, getChalk, stripIndent } from './lazy';
|
||||||
import Logger = require('./logger');
|
import Logger = require('./logger');
|
||||||
import { isV13 } from './version';
|
|
||||||
import { exists } from './which';
|
import { exists } from './which';
|
||||||
|
|
||||||
const allowedContractTypes = ['sw.application', 'sw.block'];
|
const allowedContractTypes = ['sw.application', 'sw.block'];
|
||||||
@ -105,8 +104,6 @@ export async function applyReleaseTagKeysAndValues(
|
|||||||
|
|
||||||
const LOG_LENGTH_MAX = 512 * 1024; // 512KB
|
const LOG_LENGTH_MAX = 512 * 1024; // 512KB
|
||||||
const compositionFileNames = ['docker-compose.yml', 'docker-compose.yaml'];
|
const compositionFileNames = ['docker-compose.yml', 'docker-compose.yaml'];
|
||||||
const hr =
|
|
||||||
'----------------------------------------------------------------------';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* high-level function resolving a project and creating a composition out
|
* high-level function resolving a project and creating a composition out
|
||||||
@ -257,7 +254,6 @@ export interface BuildProjectOpts {
|
|||||||
inlineLogs?: boolean;
|
inlineLogs?: boolean;
|
||||||
convertEol: boolean;
|
convertEol: boolean;
|
||||||
dockerfilePath?: string;
|
dockerfilePath?: string;
|
||||||
nogitignore: boolean; // v13: delete this line
|
|
||||||
multiDockerignore: boolean;
|
multiDockerignore: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -748,43 +744,19 @@ export function isBuildConfig(
|
|||||||
* Create a tar stream out of the local filesystem at the given directory,
|
* Create a tar stream out of the local filesystem at the given directory,
|
||||||
* while optionally applying file filters such as '.dockerignore' and
|
* while optionally applying file filters such as '.dockerignore' and
|
||||||
* optionally converting text file line endings (CRLF to LF).
|
* optionally converting text file line endings (CRLF to LF).
|
||||||
* @param dir Source directory
|
* @param dir Project directory (the '--source' command line option)
|
||||||
* @param param Options
|
* @param param TarDirectoryOptions
|
||||||
* @returns Readable stream
|
* @returns Readable stream (to be sent to the Docker Engine)
|
||||||
*/
|
*/
|
||||||
export async function tarDirectory(
|
export async function tarDirectory(
|
||||||
dir: string,
|
|
||||||
param: TarDirectoryOptions,
|
|
||||||
): Promise<import('stream').Readable> {
|
|
||||||
const { nogitignore = false } = param; // v13: delete this line
|
|
||||||
if (isV13() || nogitignore) {
|
|
||||||
return newTarDirectory(dir, param);
|
|
||||||
} else {
|
|
||||||
return (await import('./compose')).originalTarDirectory(dir, param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a tar stream out of the local filesystem at the given directory,
|
|
||||||
* while optionally applying file filters such as '.dockerignore' and
|
|
||||||
* optionally converting text file line endings (CRLF to LF).
|
|
||||||
* @param dir Source directory
|
|
||||||
* @param param Options
|
|
||||||
* @returns Readable stream
|
|
||||||
*/
|
|
||||||
async function newTarDirectory(
|
|
||||||
dir: string,
|
dir: string,
|
||||||
{
|
{
|
||||||
composition,
|
composition,
|
||||||
convertEol = false,
|
convertEol = false,
|
||||||
multiDockerignore = false,
|
multiDockerignore = false,
|
||||||
nogitignore = false, // v13: delete this line
|
|
||||||
preFinalizeCallback,
|
preFinalizeCallback,
|
||||||
}: TarDirectoryOptions,
|
}: TarDirectoryOptions,
|
||||||
): Promise<import('stream').Readable> {
|
): Promise<import('stream').Readable> {
|
||||||
if (!isV13()) {
|
|
||||||
require('assert').strict.equal(nogitignore, true);
|
|
||||||
}
|
|
||||||
const { filterFilesWithDockerignore } = await import('./ignore');
|
const { filterFilesWithDockerignore } = await import('./ignore');
|
||||||
const { toPosixPath } = (await import('resin-multibuild')).PathUtils;
|
const { toPosixPath } = (await import('resin-multibuild')).PathUtils;
|
||||||
|
|
||||||
@ -905,48 +877,6 @@ function printDockerignoreWarn(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Print a deprecation warning if any '.gitignore' or '.dockerignore' file is
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
const msg = [' ', hr, 'Using file ignore patterns from:'];
|
|
||||||
msg.push(...ignoreFiles.map((e) => `* ${e}`));
|
|
||||||
if (gitignoreFiles.length) {
|
|
||||||
msg.push(stripIndent`
|
|
||||||
.gitignore files are being considered because the --gitignore option was used.
|
|
||||||
This option is deprecated and will be removed in the next major version release.
|
|
||||||
For more information, see 'balena help ${Logger.command}'.
|
|
||||||
`);
|
|
||||||
msg.push(hr);
|
|
||||||
Logger.getLogger().logWarn(msg.join('\n'));
|
|
||||||
} else if (dockerignoreFile && process.platform === 'win32') {
|
|
||||||
msg.push(stripIndent`
|
|
||||||
The --gitignore option was used, but no .gitignore files were found.
|
|
||||||
The --gitignore option is deprecated and will be removed in the next major
|
|
||||||
version release. It prevents the use of a better dockerignore parser and
|
|
||||||
filter library that fixes several issues on Windows and improves compatibility
|
|
||||||
with 'docker build'. For more information, see 'balena help ${Logger.command}'.
|
|
||||||
`);
|
|
||||||
msg.push(hr);
|
|
||||||
Logger.getLogger().logWarn(msg.join('\n'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether the "build secrets" feature is being used and, if so,
|
* Check whether the "build secrets" feature is being used and, if so,
|
||||||
* verify that the target docker daemon is balenaEngine. If the
|
* verify that the target docker daemon is balenaEngine. If the
|
||||||
@ -1729,21 +1659,6 @@ export const composeCliFlags: flags.Input<ComposeCliFlags> = {
|
|||||||
description:
|
description:
|
||||||
'Hide the image build log output (produce less verbose output)',
|
'Hide the image build log output (produce less verbose output)',
|
||||||
}),
|
}),
|
||||||
...(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({
|
'multi-dockerignore': flags.boolean({
|
||||||
description:
|
description:
|
||||||
'Have each service use its own .dockerignore file. See "balena help build".',
|
'Have each service use its own .dockerignore file. See "balena help build".',
|
||||||
|
@ -59,7 +59,6 @@ export interface DeviceDeployOptions {
|
|||||||
registrySecrets: RegistrySecrets;
|
registrySecrets: RegistrySecrets;
|
||||||
multiDockerignore: boolean;
|
multiDockerignore: boolean;
|
||||||
nocache: boolean;
|
nocache: boolean;
|
||||||
nogitignore: boolean; // v13: delete this line
|
|
||||||
noParentCheck: boolean;
|
noParentCheck: boolean;
|
||||||
nolive: boolean;
|
nolive: boolean;
|
||||||
pull: boolean;
|
pull: boolean;
|
||||||
@ -184,7 +183,6 @@ export async function deployToDevice(opts: DeviceDeployOptions): Promise<void> {
|
|||||||
convertEol: opts.convertEol,
|
convertEol: opts.convertEol,
|
||||||
dockerfilePath: opts.dockerfilePath,
|
dockerfilePath: opts.dockerfilePath,
|
||||||
multiDockerignore: opts.multiDockerignore,
|
multiDockerignore: opts.multiDockerignore,
|
||||||
nogitignore: opts.nogitignore, // v13: delete this line
|
|
||||||
noParentCheck: opts.noParentCheck,
|
noParentCheck: opts.noParentCheck,
|
||||||
projectName: 'local',
|
projectName: 'local',
|
||||||
projectPath: opts.source,
|
projectPath: opts.source,
|
||||||
@ -204,7 +202,6 @@ export async function deployToDevice(opts: DeviceDeployOptions): Promise<void> {
|
|||||||
composition: project.composition,
|
composition: project.composition,
|
||||||
convertEol: opts.convertEol,
|
convertEol: opts.convertEol,
|
||||||
multiDockerignore: opts.multiDockerignore,
|
multiDockerignore: opts.multiDockerignore,
|
||||||
nogitignore: opts.nogitignore, // v13: delete this line
|
|
||||||
});
|
});
|
||||||
globalLogger.logDebug(`Tarring complete in ${Date.now() - tarStartTime} ms`);
|
globalLogger.logDebug(`Tarring complete in ${Date.now() - tarStartTime} ms`);
|
||||||
|
|
||||||
@ -435,7 +432,6 @@ export async function rebuildSingleTask(
|
|||||||
composition,
|
composition,
|
||||||
convertEol: opts.convertEol,
|
convertEol: opts.convertEol,
|
||||||
multiDockerignore: opts.multiDockerignore,
|
multiDockerignore: opts.multiDockerignore,
|
||||||
nogitignore: opts.nogitignore, // v13: delete this line
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const task = _.find(
|
const task = _.find(
|
||||||
|
@ -17,183 +17,11 @@
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import { promises as fs, Stats } from 'fs';
|
import { promises as fs, Stats } from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as MultiBuild from 'resin-multibuild';
|
|
||||||
|
|
||||||
import dockerIgnore = require('@zeit/dockerignore');
|
|
||||||
import ignore from 'ignore';
|
|
||||||
import type { Ignore } from '@balena/dockerignore';
|
import type { Ignore } from '@balena/dockerignore';
|
||||||
|
|
||||||
import { ExpectedError } from '../errors';
|
import { ExpectedError } from '../errors';
|
||||||
|
|
||||||
const { toPosixPath } = MultiBuild.PathUtils;
|
|
||||||
|
|
||||||
// v13: delete this enum
|
|
||||||
export enum IgnoreFileType {
|
|
||||||
DockerIgnore,
|
|
||||||
GitIgnore,
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IgnoreEntry {
|
|
||||||
pattern: string;
|
|
||||||
// The relative file path from the base path of the build context
|
|
||||||
filePath: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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[];
|
|
||||||
private gitIgnoreEntries: IgnoreEntry[];
|
|
||||||
|
|
||||||
private static ignoreFiles: Array<{
|
|
||||||
pattern: string;
|
|
||||||
type: IgnoreFileType;
|
|
||||||
allowSubdirs: boolean;
|
|
||||||
}> = [
|
|
||||||
{
|
|
||||||
pattern: '.gitignore',
|
|
||||||
type: IgnoreFileType.GitIgnore,
|
|
||||||
allowSubdirs: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
pattern: '.dockerignore',
|
|
||||||
type: IgnoreFileType.DockerIgnore,
|
|
||||||
allowSubdirs: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
public constructor(public basePath: string) {
|
|
||||||
this.dockerIgnoreEntries = [];
|
|
||||||
this.gitIgnoreEntries = [];
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @param {string} relativePath
|
|
||||||
* The relative pathname from the build context, for example a root level .gitignore should be
|
|
||||||
* ./.gitignore
|
|
||||||
* @returns IgnoreFileType
|
|
||||||
* The type of ignore file, or null
|
|
||||||
*/
|
|
||||||
public getIgnoreFileType(relativePath: string): IgnoreFileType | null {
|
|
||||||
for (const { pattern, type, allowSubdirs } of FileIgnorer.ignoreFiles) {
|
|
||||||
if (
|
|
||||||
path.basename(relativePath) === pattern &&
|
|
||||||
(allowSubdirs || path.dirname(relativePath) === '.')
|
|
||||||
) {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @param {string} fullPath
|
|
||||||
* The full path on disk of the ignore file
|
|
||||||
* @param {IgnoreFileType} type
|
|
||||||
* @returns Promise
|
|
||||||
*/
|
|
||||||
public async addIgnoreFile(
|
|
||||||
fullPath: string,
|
|
||||||
type: IgnoreFileType,
|
|
||||||
): Promise<void> {
|
|
||||||
const contents = await fs.readFile(fullPath, 'utf8');
|
|
||||||
|
|
||||||
contents.split('\n').forEach((line) => {
|
|
||||||
// ignore empty lines and comments
|
|
||||||
if (/\s*#/.test(line) || _.isEmpty(line)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.addEntry(line, fullPath, type);
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass this function as a predicate to a filter function, and it will filter
|
|
||||||
// any ignored files
|
|
||||||
public filter = (filename: string): boolean => {
|
|
||||||
const relFile = path.relative(this.basePath, filename);
|
|
||||||
|
|
||||||
// Don't ignore any metadata files
|
|
||||||
// The regex below matches `.balena/qemu` and `myservice/.balena/qemu`
|
|
||||||
// but not `some.dir.for.balena/qemu`.
|
|
||||||
if (/(^|\/)\.(balena|resin)\//.test(toPosixPath(relFile))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't ignore Dockerfile (with or without extension) or docker-compose.yml
|
|
||||||
if (
|
|
||||||
/^Dockerfile$|^Dockerfile\.\S+/.test(path.basename(relFile)) ||
|
|
||||||
path.basename(relFile) === 'docker-compose.yml'
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const dockerIgnoreHandle = dockerIgnore();
|
|
||||||
const gitIgnoreHandle = ignore();
|
|
||||||
|
|
||||||
interface IgnoreHandle {
|
|
||||||
add: (pattern: string) => void;
|
|
||||||
ignores: (file: string) => boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ignoreTypes: Array<{
|
|
||||||
handle: IgnoreHandle;
|
|
||||||
entries: IgnoreEntry[];
|
|
||||||
}> = [
|
|
||||||
{ handle: dockerIgnoreHandle, entries: this.dockerIgnoreEntries },
|
|
||||||
{ handle: gitIgnoreHandle, entries: this.gitIgnoreEntries },
|
|
||||||
];
|
|
||||||
|
|
||||||
_.each(ignoreTypes, ({ handle, entries }) => {
|
|
||||||
_.each(entries, ({ pattern, filePath }) => {
|
|
||||||
if (FileIgnorer.contains(path.posix.dirname(filePath), filename)) {
|
|
||||||
handle.add(pattern);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return !_.some(ignoreTypes, ({ handle }) => handle.ignores(relFile));
|
|
||||||
}; // tslint:disable-line:semicolon
|
|
||||||
|
|
||||||
private addEntry(
|
|
||||||
pattern: string,
|
|
||||||
filePath: string,
|
|
||||||
type: IgnoreFileType,
|
|
||||||
): void {
|
|
||||||
const entry: IgnoreEntry = { pattern, filePath };
|
|
||||||
switch (type) {
|
|
||||||
case IgnoreFileType.DockerIgnore:
|
|
||||||
this.dockerIgnoreEntries.push(entry);
|
|
||||||
break;
|
|
||||||
case IgnoreFileType.GitIgnore:
|
|
||||||
this.gitIgnoreEntries.push(entry);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given two paths, check whether the first contains the second
|
|
||||||
* @param path1 The potentially containing path
|
|
||||||
* @param path2 The potentially contained path
|
|
||||||
* @return A boolean indicating whether `path1` contains `path2`
|
|
||||||
*/
|
|
||||||
private static contains(path1: string, path2: string): boolean {
|
|
||||||
// First normalise the input, to remove any path weirdness
|
|
||||||
path1 = path.posix.normalize(path1);
|
|
||||||
path2 = path.posix.normalize(path2);
|
|
||||||
|
|
||||||
// Now test if the start of the relative path contains ../ ,
|
|
||||||
// which would tell us that path1 is not part of path2
|
|
||||||
return !/^\.\.\//.test(path.posix.relative(path1, path2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FileStats {
|
export interface FileStats {
|
||||||
filePath: string;
|
filePath: string;
|
||||||
relPath: string;
|
relPath: string;
|
||||||
|
@ -15,8 +15,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { isV13 } from './version';
|
|
||||||
|
|
||||||
export const reachingOut = `\
|
export const reachingOut = `\
|
||||||
For further help or support, visit:
|
For further help or support, visit:
|
||||||
https://www.balena.io/docs/reference/balena-cli/#support-faq-and-troubleshooting
|
https://www.balena.io/docs/reference/balena-cli/#support-faq-and-troubleshooting
|
||||||
@ -88,60 +86,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),
|
secrets.json file exists in the balena directory (usually $HOME/.balena),
|
||||||
this file will be used instead.`;
|
this file will be used instead.`;
|
||||||
|
|
||||||
const dockerignoreHelpV12 =
|
export const dockerignoreHelp =
|
||||||
'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 releases older than v12.0.0 also took .gitignore files into account.
|
|
||||||
This behavior is deprecated, but may still be enabled with the --gitignore (-g)
|
|
||||||
option if compatibility is required. This option is mutually exclusive with
|
|
||||||
--multi-dockerignore (-m) and will be removed in the CLI's next major version
|
|
||||||
release (v13).
|
|
||||||
|
|
||||||
Default .dockerignore patterns \n` +
|
|
||||||
`When --gitignore (-g) is NOT used (i.e. when not in v11 compatibility mode), 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 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`;
|
|
||||||
|
|
||||||
const dockerignoreHelpV13 =
|
|
||||||
'DOCKERIGNORE AND GITIGNORE FILES \n' +
|
'DOCKERIGNORE AND GITIGNORE FILES \n' +
|
||||||
`By default, the balena CLI will use a single ".dockerignore" file (if any) at
|
`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
|
the project root (--source directory) in order to decide which source files to
|
||||||
@ -191,10 +136,6 @@ adding exception patterns to the applicable .dockerignore file(s), for example
|
|||||||
- https://docs.docker.com/engine/reference/builder/#dockerignore-file
|
- https://docs.docker.com/engine/reference/builder/#dockerignore-file
|
||||||
- https://www.npmjs.com/package/@balena/dockerignore`;
|
- https://www.npmjs.com/package/@balena/dockerignore`;
|
||||||
|
|
||||||
export const dockerignoreHelp = isV13()
|
|
||||||
? dockerignoreHelpV13
|
|
||||||
: dockerignoreHelpV12;
|
|
||||||
|
|
||||||
export const applicationIdInfo = `\
|
export const applicationIdInfo = `\
|
||||||
Fleets may be specified by fleet name, slug, or numeric ID. Fleet slugs are
|
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
|
the recommended option, as they are unique and unambiguous. Slugs can be
|
||||||
|
@ -50,7 +50,6 @@ export interface RemoteBuild {
|
|||||||
source: string;
|
source: string;
|
||||||
auth: string;
|
auth: string;
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
nogitignore: boolean; // v13: delete this line
|
|
||||||
opts: BuildOpts;
|
opts: BuildOpts;
|
||||||
sdk: BalenaSDK;
|
sdk: BalenaSDK;
|
||||||
// For internal use
|
// For internal use
|
||||||
@ -323,7 +322,6 @@ async function getTarStream(build: RemoteBuild): Promise<Stream.Readable> {
|
|||||||
preFinalizeCallback: preFinalizeCb,
|
preFinalizeCallback: preFinalizeCb,
|
||||||
convertEol: build.opts.convertEol,
|
convertEol: build.opts.convertEol,
|
||||||
multiDockerignore: build.opts.multiDockerignore,
|
multiDockerignore: build.opts.multiDockerignore,
|
||||||
nogitignore: build.nogitignore, // v13: delete this line
|
|
||||||
});
|
});
|
||||||
globalLogger.logDebug(
|
globalLogger.logDebug(
|
||||||
`Tarring complete in ${Date.now() - tarStartTime} ms`,
|
`Tarring complete in ${Date.now() - tarStartTime} ms`,
|
||||||
|
@ -200,7 +200,6 @@
|
|||||||
"@sentry/node": "^6.13.2",
|
"@sentry/node": "^6.13.2",
|
||||||
"@types/fast-levenshtein": "0.0.1",
|
"@types/fast-levenshtein": "0.0.1",
|
||||||
"@types/update-notifier": "^4.1.1",
|
"@types/update-notifier": "^4.1.1",
|
||||||
"@zeit/dockerignore": "0.0.3",
|
|
||||||
"JSONStream": "^1.0.3",
|
"JSONStream": "^1.0.3",
|
||||||
"balena-config-json": "^4.2.0",
|
"balena-config-json": "^4.2.0",
|
||||||
"balena-device-init": "^6.0.0",
|
"balena-device-init": "^6.0.0",
|
||||||
@ -241,7 +240,6 @@
|
|||||||
"global-tunnel-ng": "^2.1.1",
|
"global-tunnel-ng": "^2.1.1",
|
||||||
"got": "^11.8.2",
|
"got": "^11.8.2",
|
||||||
"humanize": "0.0.9",
|
"humanize": "0.0.9",
|
||||||
"ignore": "^5.1.8",
|
|
||||||
"inquirer": "^7.3.3",
|
"inquirer": "^7.3.3",
|
||||||
"is-elevated": "^3.0.0",
|
"is-elevated": "^3.0.0",
|
||||||
"is-root": "^2.1.0",
|
"is-root": "^2.1.0",
|
||||||
|
@ -22,7 +22,6 @@ import { promises as fs } from 'fs';
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
import { stripIndent } from '../../build/utils/lazy';
|
import { stripIndent } from '../../build/utils/lazy';
|
||||||
import { isV13 } from '../../build/utils/version';
|
|
||||||
import { BalenaAPIMock } from '../nock/balena-api-mock';
|
import { BalenaAPIMock } from '../nock/balena-api-mock';
|
||||||
import { expectStreamNoCRLF, testDockerBuildStream } from '../docker-build';
|
import { expectStreamNoCRLF, testDockerBuildStream } from '../docker-build';
|
||||||
import { DockerMock, dockerResponsePath } from '../nock/docker-mock';
|
import { DockerMock, dockerResponsePath } from '../nock/docker-mock';
|
||||||
@ -141,9 +140,7 @@ describe('balena build', function () {
|
|||||||
docker.expectGetInfo({});
|
docker.expectGetInfo({});
|
||||||
docker.expectGetManifestBusybox();
|
docker.expectGetManifestBusybox();
|
||||||
await testDockerBuildStream({
|
await testDockerBuildStream({
|
||||||
commandLine: `build ${projectPath} --deviceType nuc --arch amd64 ${
|
commandLine: `build ${projectPath} --deviceType nuc --arch amd64`,
|
||||||
isV13() ? '' : '-g'
|
|
||||||
}`,
|
|
||||||
dockerMock: docker,
|
dockerMock: docker,
|
||||||
expectedFilesByService: { main: expectedFiles },
|
expectedFilesByService: { main: expectedFiles },
|
||||||
expectedQueryParamsByService: {
|
expectedQueryParamsByService: {
|
||||||
@ -297,9 +294,7 @@ describe('balena build', function () {
|
|||||||
docker.expectGetInfo({ OperatingSystem: 'balenaOS 2.44.0+rev1' });
|
docker.expectGetInfo({ OperatingSystem: 'balenaOS 2.44.0+rev1' });
|
||||||
docker.expectGetManifestBusybox();
|
docker.expectGetManifestBusybox();
|
||||||
await testDockerBuildStream({
|
await testDockerBuildStream({
|
||||||
commandLine: `build ${projectPath} --emulated --deviceType ${deviceType} --arch ${arch} ${
|
commandLine: `build ${projectPath} --emulated --deviceType ${deviceType} --arch ${arch}`,
|
||||||
isV13() ? '' : '--nogitignore'
|
|
||||||
}`,
|
|
||||||
dockerMock: docker,
|
dockerMock: docker,
|
||||||
expectedFilesByService: { main: expectedFiles },
|
expectedFilesByService: { main: expectedFiles },
|
||||||
expectedQueryParamsByService: {
|
expectedQueryParamsByService: {
|
||||||
@ -448,9 +443,7 @@ describe('balena build', function () {
|
|||||||
docker.expectGetManifestNucAlpine();
|
docker.expectGetManifestNucAlpine();
|
||||||
docker.expectGetManifestBusybox();
|
docker.expectGetManifestBusybox();
|
||||||
await testDockerBuildStream({
|
await testDockerBuildStream({
|
||||||
commandLine: `build ${projectPath} --deviceType nuc --arch amd64 --convert-eol ${
|
commandLine: `build ${projectPath} --deviceType nuc --arch amd64 --convert-eol -B COMPOSE_ARG=A -B barg=b --cache-from my/img1,my/img2`,
|
||||||
isV13() ? '' : '-G'
|
|
||||||
} -B COMPOSE_ARG=A -B barg=b --cache-from my/img1,my/img2`,
|
|
||||||
dockerMock: docker,
|
dockerMock: docker,
|
||||||
expectedFilesByService,
|
expectedFilesByService,
|
||||||
expectedQueryParamsByService,
|
expectedQueryParamsByService,
|
||||||
|
@ -23,7 +23,6 @@ import * as nock from 'nock';
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as sinon from 'sinon';
|
import * as sinon from 'sinon';
|
||||||
|
|
||||||
import { isV13 } from '../../build/utils/version';
|
|
||||||
import { BalenaAPIMock } from '../nock/balena-api-mock';
|
import { BalenaAPIMock } from '../nock/balena-api-mock';
|
||||||
import { expectStreamNoCRLF, testDockerBuildStream } from '../docker-build';
|
import { expectStreamNoCRLF, testDockerBuildStream } from '../docker-build';
|
||||||
import { DockerMock, dockerResponsePath } from '../nock/docker-mock';
|
import { DockerMock, dockerResponsePath } from '../nock/docker-mock';
|
||||||
@ -149,9 +148,7 @@ describe('balena deploy', function () {
|
|||||||
docker.expectGetManifestBusybox();
|
docker.expectGetManifestBusybox();
|
||||||
|
|
||||||
await testDockerBuildStream({
|
await testDockerBuildStream({
|
||||||
commandLine: `deploy testApp --build --source ${projectPath} ${
|
commandLine: `deploy testApp --build --source ${projectPath}`,
|
||||||
isV13() ? '' : '-G'
|
|
||||||
}`,
|
|
||||||
dockerMock: docker,
|
dockerMock: docker,
|
||||||
expectedFilesByService: { main: expectedFiles },
|
expectedFilesByService: { main: expectedFiles },
|
||||||
expectedQueryParamsByService: { main: commonQueryParams },
|
expectedQueryParamsByService: { main: commonQueryParams },
|
||||||
@ -315,9 +312,7 @@ describe('balena deploy', function () {
|
|||||||
sinon.stub(process, 'exit');
|
sinon.stub(process, 'exit');
|
||||||
|
|
||||||
await testDockerBuildStream({
|
await testDockerBuildStream({
|
||||||
commandLine: `deploy testApp --build --source ${projectPath} --noconvert-eol ${
|
commandLine: `deploy testApp --build --source ${projectPath} --noconvert-eol`,
|
||||||
isV13() ? '' : '-G'
|
|
||||||
}`,
|
|
||||||
dockerMock: docker,
|
dockerMock: docker,
|
||||||
expectedFilesByService: { main: expectedFiles },
|
expectedFilesByService: { main: expectedFiles },
|
||||||
expectedQueryParamsByService: { main: commonQueryParams },
|
expectedQueryParamsByService: { main: commonQueryParams },
|
||||||
|
@ -19,7 +19,6 @@ import { expect } from 'chai';
|
|||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
import { isV13 } from '../../build/utils/version';
|
|
||||||
import { BalenaAPIMock } from '../nock/balena-api-mock';
|
import { BalenaAPIMock } from '../nock/balena-api-mock';
|
||||||
import { BuilderMock, builderResponsePath } from '../nock/builder-mock';
|
import { BuilderMock, builderResponsePath } from '../nock/builder-mock';
|
||||||
import { expectStreamNoCRLF, testPushBuildStream } from '../docker-build';
|
import { expectStreamNoCRLF, testPushBuildStream } from '../docker-build';
|
||||||
@ -37,7 +36,6 @@ import {
|
|||||||
const repoPath = path.normalize(path.join(__dirname, '..', '..'));
|
const repoPath = path.normalize(path.join(__dirname, '..', '..'));
|
||||||
const projectsPath = path.join(repoPath, 'tests', 'test-data', 'projects');
|
const projectsPath = path.join(repoPath, 'tests', 'test-data', 'projects');
|
||||||
|
|
||||||
const itNoV13 = isV13() ? it.skip : it;
|
|
||||||
const itNoWin = process.platform === 'win32' ? it.skip : it;
|
const itNoWin = process.platform === 'win32' ? it.skip : it;
|
||||||
|
|
||||||
const commonResponseLines = {
|
const commonResponseLines = {
|
||||||
@ -82,9 +80,6 @@ const commonQueryParams = [
|
|||||||
['isdraft', 'false'],
|
['isdraft', 'false'],
|
||||||
];
|
];
|
||||||
|
|
||||||
const hr =
|
|
||||||
'----------------------------------------------------------------------';
|
|
||||||
|
|
||||||
describe('balena push', function () {
|
describe('balena push', function () {
|
||||||
let api: BalenaAPIMock;
|
let api: BalenaAPIMock;
|
||||||
let builder: BuilderMock;
|
let builder: BuilderMock;
|
||||||
@ -240,76 +235,7 @@ describe('balena push', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
itNoV13(
|
it('should create the expected tar stream (single container, dockerignore1)', async () => {
|
||||||
'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],
|
|
||||||
];
|
|
||||||
|
|
||||||
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(
|
const projectPath = path.join(
|
||||||
projectsPath,
|
projectsPath,
|
||||||
'no-docker-compose',
|
'no-docker-compose',
|
||||||
@ -352,7 +278,7 @@ describe('balena push', function () {
|
|||||||
// (with a mismatched fileSize 13 vs 5 for 'symlink-a.txt'), ensure that the
|
// (with a mismatched fileSize 13 vs 5 for 'symlink-a.txt'), ensure that the
|
||||||
// `core.symlinks` property is set to `true` in the `.git/config` file. Ref:
|
// `core.symlinks` property is set to `true` in the `.git/config` file. Ref:
|
||||||
// https://git-scm.com/docs/git-config#Documentation/git-config.txt-coresymlinks
|
// https://git-scm.com/docs/git-config#Documentation/git-config.txt-coresymlinks
|
||||||
it('should create the expected tar stream (single container, symbolic links, --gitignore)', async () => {
|
it('should create the expected tar stream (single container, symbolic links)', async () => {
|
||||||
const projectPath = path.join(
|
const projectPath = path.join(
|
||||||
projectsPath,
|
projectsPath,
|
||||||
'no-docker-compose',
|
'no-docker-compose',
|
||||||
@ -366,12 +292,6 @@ describe('balena push', function () {
|
|||||||
'lib/src-b.txt': { fileSize: 5, type: 'file' },
|
'lib/src-b.txt': { fileSize: 5, type: 'file' },
|
||||||
'src/src-b.txt': { fileSize: 5, type: 'file' },
|
'src/src-b.txt': { fileSize: 5, type: 'file' },
|
||||||
'symlink-a.txt': { fileSize: 5, type: 'file' },
|
'symlink-a.txt': { fileSize: 5, type: 'file' },
|
||||||
...(isWindows
|
|
||||||
? {
|
|
||||||
'lib/src-a.txt': { fileSize: 5, type: 'file' },
|
|
||||||
'src/src-a.txt': { fileSize: 5, type: 'file' },
|
|
||||||
}
|
|
||||||
: {}),
|
|
||||||
};
|
};
|
||||||
const regSecretsPath = await addRegSecretsEntries(expectedFiles);
|
const regSecretsPath = await addRegSecretsEntries(expectedFiles);
|
||||||
const responseFilename = 'build-POST-v3.json';
|
const responseFilename = 'build-POST-v3.json';
|
||||||
@ -379,27 +299,11 @@ describe('balena push', function () {
|
|||||||
path.join(builderResponsePath, responseFilename),
|
path.join(builderResponsePath, responseFilename),
|
||||||
'utf8',
|
'utf8',
|
||||||
);
|
);
|
||||||
const expectedResponseLines =
|
const expectedResponseLines = commonResponseLines[responseFilename];
|
||||||
!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({
|
await testPushBuildStream({
|
||||||
builderMock: builder,
|
builderMock: builder,
|
||||||
commandLine: `push testApp -s ${projectPath} -R ${regSecretsPath} ${
|
commandLine: `push testApp -s ${projectPath} -R ${regSecretsPath}`,
|
||||||
isV13() ? '' : '--gitignore'
|
|
||||||
}`,
|
|
||||||
expectedFiles,
|
expectedFiles,
|
||||||
expectedQueryParams: commonQueryParams,
|
expectedQueryParams: commonQueryParams,
|
||||||
expectedResponseLines,
|
expectedResponseLines,
|
||||||
|
@ -1,101 +0,0 @@
|
|||||||
import { expect } from 'chai';
|
|
||||||
import * as _ from 'lodash';
|
|
||||||
import * as path from 'path';
|
|
||||||
import { FileIgnorer, IgnoreFileType } from '../../build/utils/ignore';
|
|
||||||
|
|
||||||
// Note that brack notation is used intentionally when accessing private members
|
|
||||||
// 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}`);
|
|
||||||
expect(f.getIgnoreFileType('.gitignore')).to.equal(
|
|
||||||
IgnoreFileType.GitIgnore,
|
|
||||||
);
|
|
||||||
expect(f.getIgnoreFileType('.dockerignore')).to.equal(
|
|
||||||
IgnoreFileType.DockerIgnore,
|
|
||||||
);
|
|
||||||
expect(f.getIgnoreFileType('./.gitignore')).to.equal(
|
|
||||||
IgnoreFileType.GitIgnore,
|
|
||||||
);
|
|
||||||
expect(f.getIgnoreFileType('./.dockerignore')).to.equal(
|
|
||||||
IgnoreFileType.DockerIgnore,
|
|
||||||
);
|
|
||||||
|
|
||||||
// gitignore files can appear in subdirectories, but dockerignore files cannot
|
|
||||||
expect(f.getIgnoreFileType('./subdir/.gitignore')).to.equal(
|
|
||||||
IgnoreFileType.GitIgnore,
|
|
||||||
);
|
|
||||||
expect(f.getIgnoreFileType('./subdir/.dockerignore')).to.equal(null);
|
|
||||||
expect(f.getIgnoreFileType('./subdir/subdir2/.gitignore')).to.equal(
|
|
||||||
IgnoreFileType.GitIgnore,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(f.getIgnoreFileType('file')).to.equal(null);
|
|
||||||
return expect(f.getIgnoreFileType('./file')).to.equal(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should filter files from the root directory', function () {
|
|
||||||
const ignore = new FileIgnorer(`.${path.sep}`);
|
|
||||||
ignore['gitIgnoreEntries'] = [
|
|
||||||
{ pattern: '*.ignore', filePath: '.gitignore' },
|
|
||||||
];
|
|
||||||
ignore['dockerIgnoreEntries'] = [
|
|
||||||
{ pattern: '*.ignore2', filePath: '.dockerignore' },
|
|
||||||
];
|
|
||||||
const files = [
|
|
||||||
'a',
|
|
||||||
'a/b',
|
|
||||||
'a/b/c',
|
|
||||||
'file.ignore',
|
|
||||||
'file2.ignore',
|
|
||||||
'file.ignore2',
|
|
||||||
'file2.ignore',
|
|
||||||
];
|
|
||||||
|
|
||||||
return expect(_.filter(files, ignore.filter.bind(ignore))).to.deep.equal([
|
|
||||||
'a',
|
|
||||||
'a/b',
|
|
||||||
'a/b/c',
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
return it('should filter files from subdirectories', function () {
|
|
||||||
const ignore = new FileIgnorer(`.${path.sep}`);
|
|
||||||
ignore['gitIgnoreEntries'] = [
|
|
||||||
{ pattern: '*.ignore', filePath: 'lib/.gitignore' },
|
|
||||||
];
|
|
||||||
let files = [
|
|
||||||
'test.ignore',
|
|
||||||
'root.ignore',
|
|
||||||
'lib/normal-file',
|
|
||||||
'lib/should.ignore',
|
|
||||||
'lib/thistoo.ignore',
|
|
||||||
];
|
|
||||||
expect(_.filter(files, ignore.filter.bind(ignore))).to.deep.equal([
|
|
||||||
'test.ignore',
|
|
||||||
'root.ignore',
|
|
||||||
'lib/normal-file',
|
|
||||||
]);
|
|
||||||
|
|
||||||
ignore['gitIgnoreEntries'] = [
|
|
||||||
{ pattern: '*.ignore', filePath: './lib/.gitignore' },
|
|
||||||
];
|
|
||||||
files = [
|
|
||||||
'test.ignore',
|
|
||||||
'root.ignore',
|
|
||||||
'lib/normal-file',
|
|
||||||
'lib/should.ignore',
|
|
||||||
'lib/thistoo.ignore',
|
|
||||||
];
|
|
||||||
return expect(_.filter(files, ignore.filter.bind(ignore))).to.deep.equal([
|
|
||||||
'test.ignore',
|
|
||||||
'root.ignore',
|
|
||||||
'lib/normal-file',
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -33,8 +33,6 @@ interface TarFiles {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const itSkipWindows = process.platform === 'win32' ? it.skip : it;
|
|
||||||
|
|
||||||
describe('compare new and old tarDirectory implementations', function () {
|
describe('compare new and old tarDirectory implementations', function () {
|
||||||
const extraContent = 'extra';
|
const extraContent = 'extra';
|
||||||
const extraEntry: tar.Headers = {
|
const extraEntry: tar.Headers = {
|
||||||
@ -82,7 +80,6 @@ describe('compare new and old tarDirectory implementations', function () {
|
|||||||
|
|
||||||
const tarPack = await tarDirectory(dockerignoreProjDir, {
|
const tarPack = await tarDirectory(dockerignoreProjDir, {
|
||||||
preFinalizeCallback,
|
preFinalizeCallback,
|
||||||
nogitignore: true,
|
|
||||||
});
|
});
|
||||||
const fileList = await getTarPackFiles(tarPack);
|
const fileList = await getTarPackFiles(tarPack);
|
||||||
|
|
||||||
@ -105,67 +102,11 @@ describe('compare new and old tarDirectory implementations', function () {
|
|||||||
'symlink-a.txt': { fileSize: 5, type: 'file' },
|
'symlink-a.txt': { fileSize: 5, type: 'file' },
|
||||||
};
|
};
|
||||||
|
|
||||||
const tarPack = await tarDirectory(projectPath, { nogitignore: true });
|
const tarPack = await tarDirectory(projectPath, {});
|
||||||
const fileList = await getTarPackFiles(tarPack);
|
const fileList = await getTarPackFiles(tarPack);
|
||||||
|
|
||||||
expect(fileList).to.deep.equal(expectedFiles);
|
expect(fileList).to.deep.equal(expectedFiles);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Skip Windows because the old tarDirectory() implementation (still used when
|
|
||||||
// '--gitignore' is provided) uses the old `zeit/dockerignore` npm package
|
|
||||||
// that is broken on Windows (reason why we created `@balena/dockerignore`).
|
|
||||||
itSkipWindows('should produce a compatible tar stream', async function () {
|
|
||||||
const dockerignoreProjDir = path.join(
|
|
||||||
projectsPath,
|
|
||||||
'no-docker-compose',
|
|
||||||
'dockerignore1',
|
|
||||||
);
|
|
||||||
const oldTarPack = await tarDirectory(dockerignoreProjDir, {
|
|
||||||
preFinalizeCallback,
|
|
||||||
nogitignore: false,
|
|
||||||
});
|
|
||||||
const oldFileList = await getTarPackFiles(oldTarPack);
|
|
||||||
|
|
||||||
const newTarPack = await tarDirectory(dockerignoreProjDir, {
|
|
||||||
preFinalizeCallback,
|
|
||||||
nogitignore: true,
|
|
||||||
});
|
|
||||||
const newFileList = await getTarPackFiles(newTarPack);
|
|
||||||
|
|
||||||
const gitIgnored = ['a.txt', 'src/src-a.txt', 'src/src-c.txt'];
|
|
||||||
|
|
||||||
expect({
|
|
||||||
...newFileList,
|
|
||||||
..._.pick(oldFileList, ['.git/bar.txt']),
|
|
||||||
}).to.deep.equal({
|
|
||||||
...oldFileList,
|
|
||||||
..._.pick(newFileList, gitIgnored),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
itSkipWindows(
|
|
||||||
'should produce a compatible tar stream (symbolic links)',
|
|
||||||
async function () {
|
|
||||||
const dockerignoreProjDir = path.join(
|
|
||||||
projectsPath,
|
|
||||||
'no-docker-compose',
|
|
||||||
'dockerignore2',
|
|
||||||
);
|
|
||||||
const oldTarPack = await tarDirectory(dockerignoreProjDir, {
|
|
||||||
preFinalizeCallback,
|
|
||||||
nogitignore: false,
|
|
||||||
});
|
|
||||||
const oldFileList = await getTarPackFiles(oldTarPack);
|
|
||||||
|
|
||||||
const newTarPack = await tarDirectory(dockerignoreProjDir, {
|
|
||||||
preFinalizeCallback,
|
|
||||||
nogitignore: true,
|
|
||||||
});
|
|
||||||
const newFileList = await getTarPackFiles(newTarPack);
|
|
||||||
|
|
||||||
expect(newFileList).to.deep.equal(oldFileList);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
async function getTarPackFiles(
|
async function getTarPackFiles(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user