From 73572df7cf4d764d5c89c7289a4fe939f167ab8e Mon Sep 17 00:00:00 2001 From: Paulo Castro Date: Sat, 18 Dec 2021 23:27:59 +0000 Subject: [PATCH] build/deploy/push: Remove deprecated '--[no]gitignore' option Change-type: major --- lib/commands/build.ts | 1 - lib/commands/deploy.ts | 1 - lib/commands/push.ts | 25 ----- lib/utils/compose-types.d.ts | 4 - lib/utils/compose.js | 95 ----------------- lib/utils/compose_ts.ts | 91 +--------------- lib/utils/device/deploy.ts | 4 - lib/utils/ignore.ts | 172 ------------------------------- lib/utils/messages.ts | 61 +---------- lib/utils/remote-build.ts | 2 - package.json | 2 - tests/commands/build.spec.ts | 13 +-- tests/commands/deploy.spec.ts | 9 +- tests/commands/push.spec.ts | 104 +------------------ tests/utils/ignore.spec.ts | 101 ------------------ tests/utils/tarDirectory.spec.ts | 61 +---------- 16 files changed, 14 insertions(+), 732 deletions(-) delete mode 100644 tests/utils/ignore.spec.ts diff --git a/lib/commands/build.ts b/lib/commands/build.ts index 8c605085..141739e2 100644 --- a/lib/commands/build.ts +++ b/lib/commands/build.ts @@ -271,7 +271,6 @@ ${dockerignoreHelp} inlineLogs: composeOpts.inlineLogs, convertEol: composeOpts.convertEol, dockerfilePath: composeOpts.dockerfilePath, - nogitignore: composeOpts.nogitignore, // v13: delete this line multiDockerignore: composeOpts.multiDockerignore, }); } diff --git a/lib/commands/deploy.ts b/lib/commands/deploy.ts index 098e85de..36b469bc 100644 --- a/lib/commands/deploy.ts +++ b/lib/commands/deploy.ts @@ -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'); diff --git a/lib/commands/push.ts b/lib/commands/push.ts index d9b7622c..d66ef11c 100644 --- a/lib/commands/push.ts +++ b/lib/commands/push.ts @@ -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, diff --git a/lib/utils/compose-types.d.ts b/lib/utils/compose-types.d.ts index 8ed3c225..63521c6e 100644 --- a/lib/utils/compose-types.d.ts +++ b/lib/utils/compose-types.d.ts @@ -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; } diff --git a/lib/utils/compose.js b/lib/utils/compose.js index 2939223d..fecd67c8 100644 --- a/lib/utils/compose.js +++ b/lib/utils/compose.js @@ -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} - * - * 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 diff --git a/lib/utils/compose_ts.ts b/lib/utils/compose_ts.ts index 5f083576..c150b6ad 100644 --- a/lib/utils/compose_ts.ts +++ b/lib/utils/compose_ts.ts @@ -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 { - 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 { - 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 = { 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".', diff --git a/lib/utils/device/deploy.ts b/lib/utils/device/deploy.ts index 53d16732..61d9c970 100644 --- a/lib/utils/device/deploy.ts +++ b/lib/utils/device/deploy.ts @@ -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 { 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 { 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( diff --git a/lib/utils/ignore.ts b/lib/utils/ignore.ts index f969ca3f..42275d63 100644 --- a/lib/utils/ignore.ts +++ b/lib/utils/ignore.ts @@ -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 { - 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; diff --git a/lib/utils/messages.ts b/lib/utils/messages.ts index 3d00fef7..d1a88b7d 100644 --- a/lib/utils/messages.ts +++ b/lib/utils/messages.ts @@ -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 diff --git a/lib/utils/remote-build.ts b/lib/utils/remote-build.ts index 8b074126..f31af958 100644 --- a/lib/utils/remote-build.ts +++ b/lib/utils/remote-build.ts @@ -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 { 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`, diff --git a/package.json b/package.json index 88e025ee..056a3266 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/tests/commands/build.spec.ts b/tests/commands/build.spec.ts index 7bd709b1..ad78abb9 100644 --- a/tests/commands/build.spec.ts +++ b/tests/commands/build.spec.ts @@ -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, diff --git a/tests/commands/deploy.spec.ts b/tests/commands/deploy.spec.ts index 2067b318..4d8919f8 100644 --- a/tests/commands/deploy.spec.ts +++ b/tests/commands/deploy.spec.ts @@ -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 }, diff --git a/tests/commands/push.spec.ts b/tests/commands/push.spec.ts index c13d1370..89a815e6 100644 --- a/tests/commands/push.spec.ts +++ b/tests/commands/push.spec.ts @@ -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, diff --git a/tests/utils/ignore.spec.ts b/tests/utils/ignore.spec.ts deleted file mode 100644 index 6c035249..00000000 --- a/tests/utils/ignore.spec.ts +++ /dev/null @@ -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', - ]); - }); -}); diff --git a/tests/utils/tarDirectory.spec.ts b/tests/utils/tarDirectory.spec.ts index 551d4ca7..7d3adb2f 100644 --- a/tests/utils/tarDirectory.spec.ts +++ b/tests/utils/tarDirectory.spec.ts @@ -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(