build/deploy/push: Remove deprecated '--[no]gitignore' option

Change-type: major
This commit is contained in:
Paulo Castro 2021-12-18 23:27:59 +00:00
parent 23b42b1a2b
commit 73572df7cf
16 changed files with 14 additions and 732 deletions

View File

@ -271,7 +271,6 @@ ${dockerignoreHelp}
inlineLogs: composeOpts.inlineLogs,
convertEol: composeOpts.convertEol,
dockerfilePath: composeOpts.dockerfilePath,
nogitignore: composeOpts.nogitignore, // v13: delete this line
multiDockerignore: composeOpts.multiDockerignore,
});
}

View File

@ -319,7 +319,6 @@ ${dockerignoreHelp}
inlineLogs: composeOpts.inlineLogs,
convertEol: composeOpts.convertEol,
dockerfilePath: composeOpts.dockerfilePath,
nogitignore: composeOpts.nogitignore, // v13: delete this line
multiDockerignore: composeOpts.multiDockerignore,
});
builtImagesByService = _.keyBy(builtImages, 'serviceName');

View File

@ -47,8 +47,6 @@ interface FlagsDef {
pull: boolean;
'noparent-check': boolean;
'registry-secrets'?: string;
gitignore?: boolean; // v13: delete this flag
nogitignore?: boolean; // v13: delete this flag
nolive: boolean;
detached: boolean;
service?: string[];
@ -237,28 +235,7 @@ export default class PushCmd extends Command {
'Have each service use its own .dockerignore file. See "balena help push".',
char: 'm',
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({
description: stripIndent`
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,
auth: token,
baseUrl,
nogitignore: !options.gitignore, // v13: delete this line
sdk,
opts,
};
@ -422,7 +398,6 @@ export default class PushCmd extends Command {
multiDockerignore: options['multi-dockerignore'],
nocache: options.nocache,
pull: options.pull,
nogitignore: !options.gitignore, // v13: delete this line
noParentCheck: options['noparent-check'],
nolive: options.nolive,
detached: options.detached,

View File

@ -51,7 +51,6 @@ export interface ComposeOpts {
dockerfilePath?: string;
inlineLogs?: boolean;
multiDockerignore: boolean;
nogitignore: boolean; // v13: delete this line
noParentCheck: boolean;
projectName: string;
projectPath: string;
@ -63,8 +62,6 @@ export interface ComposeCliFlags {
dockerfile?: string;
logs: boolean;
nologs: boolean;
gitignore?: boolean; // v13: delete this line
nogitignore?: boolean; // v13: delete this line
'multi-dockerignore': boolean;
'noparent-check': boolean;
'registry-secrets'?: RegistrySecrets;
@ -102,6 +99,5 @@ interface TarDirectoryOptions {
composition?: Composition;
convertEol?: boolean;
multiDockerignore?: boolean;
nogitignore: boolean; // v13: delete this line
preFinalizeCallback?: (pack: Pack) => void | Promise<void>;
}

View File

@ -16,21 +16,13 @@
*/
import * as path from 'path';
import { ExpectedError } from '../errors';
import { getChalk } from './lazy';
import { isV13 } from './version';
/**
* @returns Promise<{import('./compose-types').ComposeOpts}>
*/
export function generateOpts(options) {
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) => ({
projectName: options.projectName,
projectPath,
@ -38,7 +30,6 @@ export function generateOpts(options) {
convertEol: !options['noconvert-eol'],
dockerfilePath: options.dockerfile,
multiDockerignore: !!options['multi-dockerignore'],
nogitignore: !options.gitignore, // v13: delete this line
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} auth

View File

@ -43,7 +43,6 @@ 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';
const allowedContractTypes = ['sw.application', 'sw.block'];
@ -105,8 +104,6 @@ export async function applyReleaseTagKeysAndValues(
const LOG_LENGTH_MAX = 512 * 1024; // 512KB
const compositionFileNames = ['docker-compose.yml', 'docker-compose.yaml'];
const hr =
'----------------------------------------------------------------------';
/**
* high-level function resolving a project and creating a composition out
@ -257,7 +254,6 @@ export interface BuildProjectOpts {
inlineLogs?: boolean;
convertEol: boolean;
dockerfilePath?: string;
nogitignore: boolean; // v13: delete this line
multiDockerignore: boolean;
}
@ -748,43 +744,19 @@ export function isBuildConfig(
* 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
* @param dir Project directory (the '--source' command line option)
* @param param TarDirectoryOptions
* @returns Readable stream (to be sent to the Docker Engine)
*/
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,
{
composition,
convertEol = false,
multiDockerignore = false,
nogitignore = false, // v13: delete this line
preFinalizeCallback,
}: TarDirectoryOptions,
): Promise<import('stream').Readable> {
if (!isV13()) {
require('assert').strict.equal(nogitignore, true);
}
const { filterFilesWithDockerignore } = await import('./ignore');
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,
* verify that the target docker daemon is balenaEngine. If the
@ -1729,21 +1659,6 @@ export const composeCliFlags: flags.Input<ComposeCliFlags> = {
description:
'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({
description:
'Have each service use its own .dockerignore file. See "balena help build".',

View File

@ -59,7 +59,6 @@ export interface DeviceDeployOptions {
registrySecrets: RegistrySecrets;
multiDockerignore: boolean;
nocache: boolean;
nogitignore: boolean; // v13: delete this line
noParentCheck: boolean;
nolive: boolean;
pull: boolean;
@ -184,7 +183,6 @@ export async function deployToDevice(opts: DeviceDeployOptions): Promise<void> {
convertEol: opts.convertEol,
dockerfilePath: opts.dockerfilePath,
multiDockerignore: opts.multiDockerignore,
nogitignore: opts.nogitignore, // v13: delete this line
noParentCheck: opts.noParentCheck,
projectName: 'local',
projectPath: opts.source,
@ -204,7 +202,6 @@ export async function deployToDevice(opts: DeviceDeployOptions): Promise<void> {
composition: project.composition,
convertEol: opts.convertEol,
multiDockerignore: opts.multiDockerignore,
nogitignore: opts.nogitignore, // v13: delete this line
});
globalLogger.logDebug(`Tarring complete in ${Date.now() - tarStartTime} ms`);
@ -435,7 +432,6 @@ export async function rebuildSingleTask(
composition,
convertEol: opts.convertEol,
multiDockerignore: opts.multiDockerignore,
nogitignore: opts.nogitignore, // v13: delete this line
});
const task = _.find(

View File

@ -17,183 +17,11 @@
import * as _ from 'lodash';
import { promises as fs, Stats } from 'fs';
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 { 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 {
filePath: string;
relPath: string;

View File

@ -15,8 +15,6 @@
* 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
@ -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),
this file will be used instead.`;
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
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 =
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
@ -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://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

View File

@ -50,7 +50,6 @@ export interface RemoteBuild {
source: string;
auth: string;
baseUrl: string;
nogitignore: boolean; // v13: delete this line
opts: BuildOpts;
sdk: BalenaSDK;
// For internal use
@ -323,7 +322,6 @@ async function getTarStream(build: RemoteBuild): Promise<Stream.Readable> {
preFinalizeCallback: preFinalizeCb,
convertEol: build.opts.convertEol,
multiDockerignore: build.opts.multiDockerignore,
nogitignore: build.nogitignore, // v13: delete this line
});
globalLogger.logDebug(
`Tarring complete in ${Date.now() - tarStartTime} ms`,

View File

@ -200,7 +200,6 @@
"@sentry/node": "^6.13.2",
"@types/fast-levenshtein": "0.0.1",
"@types/update-notifier": "^4.1.1",
"@zeit/dockerignore": "0.0.3",
"JSONStream": "^1.0.3",
"balena-config-json": "^4.2.0",
"balena-device-init": "^6.0.0",
@ -241,7 +240,6 @@
"global-tunnel-ng": "^2.1.1",
"got": "^11.8.2",
"humanize": "0.0.9",
"ignore": "^5.1.8",
"inquirer": "^7.3.3",
"is-elevated": "^3.0.0",
"is-root": "^2.1.0",

View File

@ -22,7 +22,6 @@ import { promises as fs } from 'fs';
import * as path from 'path';
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';
@ -141,9 +140,7 @@ describe('balena build', function () {
docker.expectGetInfo({});
docker.expectGetManifestBusybox();
await testDockerBuildStream({
commandLine: `build ${projectPath} --deviceType nuc --arch amd64 ${
isV13() ? '' : '-g'
}`,
commandLine: `build ${projectPath} --deviceType nuc --arch amd64`,
dockerMock: docker,
expectedFilesByService: { main: expectedFiles },
expectedQueryParamsByService: {
@ -297,9 +294,7 @@ describe('balena build', function () {
docker.expectGetInfo({ OperatingSystem: 'balenaOS 2.44.0+rev1' });
docker.expectGetManifestBusybox();
await testDockerBuildStream({
commandLine: `build ${projectPath} --emulated --deviceType ${deviceType} --arch ${arch} ${
isV13() ? '' : '--nogitignore'
}`,
commandLine: `build ${projectPath} --emulated --deviceType ${deviceType} --arch ${arch}`,
dockerMock: docker,
expectedFilesByService: { main: expectedFiles },
expectedQueryParamsByService: {
@ -448,9 +443,7 @@ describe('balena build', function () {
docker.expectGetManifestNucAlpine();
docker.expectGetManifestBusybox();
await testDockerBuildStream({
commandLine: `build ${projectPath} --deviceType nuc --arch amd64 --convert-eol ${
isV13() ? '' : '-G'
} -B COMPOSE_ARG=A -B barg=b --cache-from my/img1,my/img2`,
commandLine: `build ${projectPath} --deviceType nuc --arch amd64 --convert-eol -B COMPOSE_ARG=A -B barg=b --cache-from my/img1,my/img2`,
dockerMock: docker,
expectedFilesByService,
expectedQueryParamsByService,

View File

@ -23,7 +23,6 @@ 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';
@ -149,9 +148,7 @@ describe('balena deploy', function () {
docker.expectGetManifestBusybox();
await testDockerBuildStream({
commandLine: `deploy testApp --build --source ${projectPath} ${
isV13() ? '' : '-G'
}`,
commandLine: `deploy testApp --build --source ${projectPath}`,
dockerMock: docker,
expectedFilesByService: { main: expectedFiles },
expectedQueryParamsByService: { main: commonQueryParams },
@ -315,9 +312,7 @@ describe('balena deploy', function () {
sinon.stub(process, 'exit');
await testDockerBuildStream({
commandLine: `deploy testApp --build --source ${projectPath} --noconvert-eol ${
isV13() ? '' : '-G'
}`,
commandLine: `deploy testApp --build --source ${projectPath} --noconvert-eol`,
dockerMock: docker,
expectedFilesByService: { main: expectedFiles },
expectedQueryParamsByService: { main: commonQueryParams },

View File

@ -19,7 +19,6 @@ 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';
@ -37,7 +36,6 @@ import {
const repoPath = path.normalize(path.join(__dirname, '..', '..'));
const projectsPath = path.join(repoPath, 'tests', 'test-data', 'projects');
const itNoV13 = isV13() ? it.skip : it;
const itNoWin = process.platform === 'win32' ? it.skip : it;
const commonResponseLines = {
@ -82,9 +80,6 @@ const commonQueryParams = [
['isdraft', 'false'],
];
const hr =
'----------------------------------------------------------------------';
describe('balena push', function () {
let api: BalenaAPIMock;
let builder: BuilderMock;
@ -240,76 +235,7 @@ describe('balena push', function () {
});
});
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],
];
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 () => {
it('should create the expected tar stream (single container, dockerignore1)', async () => {
const projectPath = path.join(
projectsPath,
'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
// `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
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(
projectsPath,
'no-docker-compose',
@ -366,12 +292,6 @@ describe('balena push', function () {
'lib/src-b.txt': { fileSize: 5, type: 'file' },
'src/src-b.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 responseFilename = 'build-POST-v3.json';
@ -379,27 +299,11 @@ describe('balena push', function () {
path.join(builderResponsePath, responseFilename),
'utf8',
);
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];
const expectedResponseLines = commonResponseLines[responseFilename];
await testPushBuildStream({
builderMock: builder,
commandLine: `push testApp -s ${projectPath} -R ${regSecretsPath} ${
isV13() ? '' : '--gitignore'
}`,
commandLine: `push testApp -s ${projectPath} -R ${regSecretsPath}`,
expectedFiles,
expectedQueryParams: commonQueryParams,
expectedResponseLines,

View File

@ -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',
]);
});
});

View File

@ -33,8 +33,6 @@ interface TarFiles {
};
}
const itSkipWindows = process.platform === 'win32' ? it.skip : it;
describe('compare new and old tarDirectory implementations', function () {
const extraContent = 'extra';
const extraEntry: tar.Headers = {
@ -82,7 +80,6 @@ describe('compare new and old tarDirectory implementations', function () {
const tarPack = await tarDirectory(dockerignoreProjDir, {
preFinalizeCallback,
nogitignore: true,
});
const fileList = await getTarPackFiles(tarPack);
@ -105,67 +102,11 @@ describe('compare new and old tarDirectory implementations', function () {
'symlink-a.txt': { fileSize: 5, type: 'file' },
};
const tarPack = await tarDirectory(projectPath, { nogitignore: true });
const tarPack = await tarDirectory(projectPath, {});
const fileList = await getTarPackFiles(tarPack);
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(