Add runtime warning for unused .dockerignore files

Change-type: patch
This commit is contained in:
Paulo Castro 2020-06-20 23:05:59 +01:00
parent 2859d16b31
commit 11d1a3f5a0
7 changed files with 238 additions and 166 deletions

View File

@ -193,8 +193,12 @@ export async function tarDirectory(
readFile = fs.readFile;
}
const pack = tar.pack();
const fileStatsList = await filterFilesWithDockerignore(dir);
for (const fileStats of fileStatsList) {
const {
filteredFileList,
dockerignoreFiles,
} = await filterFilesWithDockerignore(dir);
printDockerignoreWarn(dockerignoreFiles);
for (const fileStats of filteredFileList) {
pack.entry(
{
name: toPosixPath(fileStats.relPath),
@ -212,9 +216,40 @@ export async function tarDirectory(
return pack;
}
export function printDockerignoreWarn(
dockerignoreFiles: Array<import('./ignore').FileStats>,
) {
const nonRootFiles = dockerignoreFiles.filter(
(fileStats: import('./ignore').FileStats) => {
const dirname = path.dirname(fileStats.relPath);
return !!dirname && dirname !== '.';
},
);
if (nonRootFiles.length === 0) {
return;
}
const hr =
'-------------------------------------------------------------------------------';
const msg = [
' ',
hr,
'The following .dockerignore file(s) will not be used:',
];
msg.push(...nonRootFiles.map((fileStats) => `* ${fileStats.filePath}`));
msg.push(stripIndent`
Only one .dockerignore file at the source folder (project root) is used.
Additional .dockerignore files are disregarded. Microservices (multicontainer)
apps should place the .dockerignore file alongside the docker-compose.yml file.
See issue: https://github.com/balena-io/balena-cli/issues/1870
See also CLI v12 release notes: https://git.io/Jf7hz
`);
msg.push(hr);
Logger.getLogger().logWarn(msg.join('\n'));
}
/**
* Print a deprecation warning if any '.gitignore' or '.dockerignore' file is
* found and the --gitignore (-g) option has been provided.
* 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
*/
@ -229,22 +264,22 @@ export function printGitignoreWarn(
const hr =
'-------------------------------------------------------------------------------';
const msg = [' ', hr, 'Using file ignore patterns from:'];
msg.push(...ignoreFiles);
msg.push(...ignoreFiles.map((e) => `* ${e}`));
if (gitignoreFiles.length) {
msg.push(stripIndent`
Note: .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}'.
.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 not .gitignore files were found.
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}'.
with 'docker build'. For more information, see 'balena help ${Logger.command}'.
`);
msg.push(hr);
Logger.getLogger().logWarn(msg.join('\n'));

View File

@ -190,7 +190,7 @@ export class FileIgnorer {
}
}
interface FileStats {
export interface FileStats {
filePath: string;
relPath: string;
stats: fs.Stats;
@ -256,7 +256,7 @@ async function readDockerIgnoreFile(projectDir: string): Promise<string> {
*/
export async function filterFilesWithDockerignore(
projectDir: string,
): Promise<FileStats[]> {
): Promise<{ filteredFileList: FileStats[]; dockerignoreFiles: FileStats[] }> {
// path.resolve() also converts forward slashes to backslashes on Windows
projectDir = path.resolve(projectDir);
const dockerIgnoreStr = await readDockerIgnoreFile(projectDir);
@ -276,5 +276,12 @@ export async function filterFilesWithDockerignore(
]);
const files = await listFiles(projectDir);
return files.filter((file: FileStats) => !ig.ignores(file.relPath));
const dockerignoreFiles: FileStats[] = [];
const filteredFileList = files.filter((file: FileStats) => {
if (path.basename(file.relPath) === '.dockerignore') {
dockerignoreFiles.push(file);
}
return !ig.ignores(file.relPath);
});
return { filteredFileList, dockerignoreFiles };
}

View File

@ -24,7 +24,6 @@ import mock = require('mock-require');
import { fs } from 'mz';
import * as path from 'path';
import { isV12 } from '../../build/utils/version';
import { BalenaAPIMock } from '../balena-api-mock';
import { expectStreamNoCRLF, testDockerBuildStream } from '../docker-build';
import { DockerMock, dockerResponsePath } from '../docker-mock';
@ -87,12 +86,12 @@ describe('balena build', function () {
it('should create the expected tar stream (single container)', async () => {
const projectPath = path.join(projectsPath, 'no-docker-compose', 'basic');
const isV12W = isWindows && isV12();
const expectedFiles: ExpectedTarStreamFiles = {
'src/.dockerignore': { fileSize: 16, type: 'file' },
'src/start.sh': { fileSize: 89, type: 'file' },
'src/windows-crlf.sh': {
fileSize: isV12W ? 68 : 70,
testStream: isV12W ? expectStreamNoCRLF : undefined,
fileSize: isWindows ? 68 : 70,
testStream: isWindows ? expectStreamNoCRLF : undefined,
type: 'file',
},
Dockerfile: { fileSize: 88, type: 'file' },
@ -107,13 +106,11 @@ describe('balena build', function () {
...commonResponseLines[responseFilename],
`[Info] No "docker-compose.yml" file found at "${projectPath}"`,
`[Info] Creating default composition with source: "${projectPath}"`,
isV12()
? '[Build] main Step 1/4 : FROM busybox'
: '[Build] main Image size: 1.14 MB',
'[Build] main Step 1/4 : FROM busybox',
];
if (isWindows) {
const fname = path.join(projectPath, 'src', 'windows-crlf.sh');
if (isV12()) {
if (isWindows) {
expectedResponseLines.push(
`[Info] Converting line endings CRLF -> LF for file: ${fname}`,
);
@ -142,7 +139,6 @@ describe('balena build', function () {
// downloading and installing QEMU
itSS('should create the expected tar stream (--emulated)', async () => {
const projectPath = path.join(projectsPath, 'no-docker-compose', 'basic');
const isV12W = isWindows && isV12();
const transposedDockerfile =
stripIndent`
FROM busybox
@ -151,10 +147,11 @@ describe('balena build', function () {
RUN ["/tmp/qemu-execve","-execve","/bin/sh","-c","chmod a+x /usr/src/*.sh"]
CMD ["/usr/src/start.sh"]` + '\n';
const expectedFiles: ExpectedTarStreamFiles = {
'src/.dockerignore': { fileSize: 16, type: 'file' },
'src/start.sh': { fileSize: 89, type: 'file' },
'src/windows-crlf.sh': {
fileSize: isV12W ? 68 : 70,
testStream: isV12W ? expectStreamNoCRLF : undefined,
fileSize: isWindows ? 68 : 70,
testStream: isWindows ? expectStreamNoCRLF : undefined,
type: 'file',
},
Dockerfile: {
@ -174,23 +171,25 @@ describe('balena build', function () {
`[Info] Creating default composition with source: "${projectPath}"`,
'[Info] Building for rpi/raspberry-pi',
'[Info] Emulation is enabled',
isV12()
? '[Build] main Step 1/4 : FROM busybox'
: '[Build] main Image size: 1.14 MB',
...[
'[Warn] -------------------------------------------------------------------------------',
'[Warn] The following .dockerignore file(s) will not be used:',
`[Warn] * ${path.join(projectPath, 'src', '.dockerignore')}`,
'[Warn] Only one .dockerignore file at the source folder (project root) is used.',
'[Warn] Additional .dockerignore files are disregarded. Microservices (multicontainer)',
'[Warn] apps should place the .dockerignore file alongside the docker-compose.yml file.',
'[Warn] See issue: https://github.com/balena-io/balena-cli/issues/1870',
'[Warn] See also CLI v12 release notes: https://git.io/Jf7hz',
'[Warn] -------------------------------------------------------------------------------',
],
'[Build] main Step 1/4 : FROM busybox',
'[Success] Build succeeded!',
];
if (isWindows) {
const fname = path.join(projectPath, 'src', 'windows-crlf.sh');
if (isV12()) {
expectedResponseLines.push(
`[Info] Converting line endings CRLF -> LF for file: ${fname}`,
);
} else {
expectedResponseLines.push(
`[Warn] CRLF (Windows) line endings detected in file: ${fname}`,
'[Warn] Windows-format line endings were detected in some files. Consider using the `--convert-eol` option.',
);
}
expectedResponseLines.push(
`[Info] Converting line endings CRLF -> LF for file: ${fname}`,
);
}
const arch = 'rpi';
const deviceType = 'raspberry-pi';
@ -230,12 +229,11 @@ describe('balena build', function () {
it('should create the expected tar stream (single container, --[no]convert-eol)', async () => {
const projectPath = path.join(projectsPath, 'no-docker-compose', 'basic');
const eol = isWindows && !isV12();
const expectedFiles: ExpectedTarStreamFiles = {
'src/.dockerignore': { fileSize: 16, type: 'file' },
'src/start.sh': { fileSize: 89, type: 'file' },
'src/windows-crlf.sh': {
fileSize: eol ? 68 : 70,
testStream: eol ? expectStreamNoCRLF : undefined,
fileSize: 70,
type: 'file',
},
Dockerfile: { fileSize: 88, type: 'file' },
@ -250,28 +248,29 @@ describe('balena build', function () {
...commonResponseLines[responseFilename],
`[Info] No "docker-compose.yml" file found at "${projectPath}"`,
`[Info] Creating default composition with source: "${projectPath}"`,
isV12()
? '[Build] main Step 1/4 : FROM busybox'
: '[Build] main Image size: 1.14 MB',
...[
'[Warn] -------------------------------------------------------------------------------',
'[Warn] The following .dockerignore file(s) will not be used:',
`[Warn] * ${path.join(projectPath, 'src', '.dockerignore')}`,
'[Warn] Only one .dockerignore file at the source folder (project root) is used.',
'[Warn] Additional .dockerignore files are disregarded. Microservices (multicontainer)',
'[Warn] apps should place the .dockerignore file alongside the docker-compose.yml file.',
'[Warn] See issue: https://github.com/balena-io/balena-cli/issues/1870',
'[Warn] See also CLI v12 release notes: https://git.io/Jf7hz',
'[Warn] -------------------------------------------------------------------------------',
],
'[Build] main Step 1/4 : FROM busybox',
];
if (isWindows) {
const fname = path.join(projectPath, 'src', 'windows-crlf.sh');
if (isV12()) {
expectedResponseLines.push(
`[Warn] CRLF (Windows) line endings detected in file: ${fname}`,
'[Warn] Windows-format line endings were detected in some files, but were not converted due to `--noconvert-eol` option.',
);
} else {
expectedResponseLines.push(
`[Info] Converting line endings CRLF -> LF for file: ${fname}`,
);
}
expectedResponseLines.push(
`[Warn] CRLF (Windows) line endings detected in file: ${fname}`,
'[Warn] Windows-format line endings were detected in some files, but were not converted due to `--noconvert-eol` option.',
);
}
docker.expectGetInfo({});
await testDockerBuildStream({
commandLine: isV12()
? `build ${projectPath} --deviceType nuc --arch amd64 --noconvert-eol`
: `build ${projectPath} --deviceType nuc --arch amd64 --convert-eol`,
commandLine: `build ${projectPath} --deviceType nuc --arch amd64 --noconvert-eol`,
dockerMock: docker,
expectedFilesByService: { main: expectedFiles },
expectedQueryParamsByService: { main: commonQueryParams },
@ -302,6 +301,7 @@ describe('balena build', function () {
'file1.sh': { fileSize: 12, type: 'file' },
},
service2: {
'.dockerignore': { fileSize: 14, type: 'file' },
'Dockerfile-alt': { fileSize: 40, type: 'file' },
'file2-crlf.sh': {
fileSize: isWindows ? 12 : 14,
@ -328,15 +328,20 @@ describe('balena build', function () {
};
const expectedResponseLines: string[] = [
...commonResponseLines[responseFilename],
...(isV12()
? [
'[Build] service1 Step 1/4 : FROM busybox',
'[Build] service2 Step 1/4 : FROM busybox',
]
: [
`[Build] service1 Image size: 1.14 MB`,
`[Build] service2 Image size: 1.14 MB`,
]),
...[
'[Build] service1 Step 1/4 : FROM busybox',
'[Build] service2 Step 1/4 : FROM busybox',
],
...[
'[Warn] The following .dockerignore file(s) will not be used:',
`[Warn] * ${path.join(projectPath, 'service2', '.dockerignore')}`,
'[Warn] Only one .dockerignore file at the source folder (project root) is used.',
'[Warn] Additional .dockerignore files are disregarded. Microservices (multicontainer)',
'[Warn] apps should place the .dockerignore file alongside the docker-compose.yml file.',
'[Warn] See issue: https://github.com/balena-io/balena-cli/issues/1870',
'[Warn] See also CLI v12 release notes: https://git.io/Jf7hz',
'[Warn] -------------------------------------------------------------------------------',
],
];
if (isWindows) {
expectedResponseLines.push(

View File

@ -23,7 +23,6 @@ import { fs } from 'mz';
import * as path from 'path';
import * as sinon from 'sinon';
import { isV12 } from '../../build/utils/version';
import { BalenaAPIMock } from '../balena-api-mock';
import { expectStreamNoCRLF, testDockerBuildStream } from '../docker-build';
import { DockerMock, dockerResponsePath } from '../docker-mock';
@ -39,9 +38,7 @@ const commonResponseLines = {
'[Info] Docker Desktop detected (daemon architecture: "x86_64")',
'[Info] Docker itself will determine and enable architecture emulation if required,',
'[Info] without balena-cli intervention and regardless of the --emulated option.',
isV12()
? '[Build] main Step 1/4 : FROM busybox'
: '[Build] main Image size: 1.14 MB',
'[Build] main Step 1/4 : FROM busybox',
'[Info] Creating release...',
'[Info] Pushing images to registry...',
'[Info] Saving release...',
@ -59,20 +56,8 @@ const commonQueryParams = [
describe('balena deploy', function () {
let api: BalenaAPIMock;
let docker: DockerMock;
let sentryStatus: boolean | undefined;
const isWindows = process.platform === 'win32';
this.beforeAll(async () => {
sentryStatus = await switchSentry(false);
sinon.stub(process, 'exit');
});
this.afterAll(async () => {
await switchSentry(sentryStatus);
// @ts-ignore
process.exit.restore();
});
this.beforeEach(() => {
api = new BalenaAPIMock();
docker = new DockerMock();
@ -106,12 +91,12 @@ describe('balena deploy', function () {
it('should create the expected --build tar stream (single container)', async () => {
const projectPath = path.join(projectsPath, 'no-docker-compose', 'basic');
const isV12W = isWindows && isV12();
const expectedFiles: ExpectedTarStreamFiles = {
'src/.dockerignore': { fileSize: 16, type: 'file' },
'src/start.sh': { fileSize: 89, type: 'file' },
'src/windows-crlf.sh': {
fileSize: isV12W ? 68 : 70,
testStream: isV12W ? expectStreamNoCRLF : undefined,
fileSize: isWindows ? 68 : 70,
testStream: isWindows ? expectStreamNoCRLF : undefined,
type: 'file',
},
Dockerfile: { fileSize: 88, type: 'file' },
@ -126,19 +111,23 @@ describe('balena deploy', function () {
...commonResponseLines[responseFilename],
`[Info] No "docker-compose.yml" file found at "${projectPath}"`,
`[Info] Creating default composition with source: "${projectPath}"`,
...[
'[Warn] -------------------------------------------------------------------------------',
'[Warn] The following .dockerignore file(s) will not be used:',
`[Warn] * ${path.join(projectPath, 'src', '.dockerignore')}`,
'[Warn] Only one .dockerignore file at the source folder (project root) is used.',
'[Warn] Additional .dockerignore files are disregarded. Microservices (multicontainer)',
'[Warn] apps should place the .dockerignore file alongside the docker-compose.yml file.',
'[Warn] See issue: https://github.com/balena-io/balena-cli/issues/1870',
'[Warn] See also CLI v12 release notes: https://git.io/Jf7hz',
'[Warn] -------------------------------------------------------------------------------',
],
];
if (isWindows) {
const fname = path.join(projectPath, 'src', 'windows-crlf.sh');
if (isV12()) {
expectedResponseLines.push(
`[Info] Converting line endings CRLF -> LF for file: ${fname}`,
);
} else {
expectedResponseLines.push(
`[Warn] CRLF (Windows) line endings detected in file: ${fname}`,
'[Warn] Windows-format line endings were detected in some files. Consider using the `--convert-eol` option.',
);
}
expectedResponseLines.push(
`[Info] Converting line endings CRLF -> LF for file: ${fname}`,
);
}
api.expectPatchImage({});
@ -158,8 +147,10 @@ describe('balena deploy', function () {
});
it('should update a release with status="failed" on error (single container)', async () => {
let sentryStatus: boolean | undefined;
const projectPath = path.join(projectsPath, 'no-docker-compose', 'basic');
const expectedFiles: ExpectedTarStreamFiles = {
'src/.dockerignore': { fileSize: 16, type: 'file' },
'src/start.sh': { fileSize: 89, type: 'file' },
'src/windows-crlf.sh': { fileSize: 70, type: 'file' },
Dockerfile: { fileSize: 88, type: 'file' },
@ -199,24 +190,34 @@ describe('balena deploy', function () {
},
});
await testDockerBuildStream({
commandLine: `deploy testApp --build --source ${projectPath} --noconvert-eol -G`,
dockerMock: docker,
expectedFilesByService: { main: expectedFiles },
expectedQueryParamsByService: { main: commonQueryParams },
expectedErrorLines,
expectedExitCode,
expectedResponseLines,
projectPath,
responseBody,
responseCode: 200,
services: ['main'],
});
try {
sentryStatus = await switchSentry(false);
sinon.stub(process, 'exit');
await testDockerBuildStream({
commandLine: `deploy testApp --build --source ${projectPath} --noconvert-eol -G`,
dockerMock: docker,
expectedFilesByService: { main: expectedFiles },
expectedQueryParamsByService: { main: commonQueryParams },
expectedErrorLines,
expectedExitCode,
expectedResponseLines,
projectPath,
responseBody,
responseCode: 200,
services: ['main'],
});
} finally {
await switchSentry(sentryStatus);
// @ts-ignore
process.exit.restore();
}
});
});
describe('balena deploy: project validation', function () {
let api: BalenaAPIMock;
this.beforeEach(() => {
api = new BalenaAPIMock();
api.expectGetWhoAmI({ optional: true, persist: true });

View File

@ -22,7 +22,6 @@ import { expect } from 'chai';
import { fs } from 'mz';
import * as path from 'path';
import { isV12 } from '../../build/utils/version';
import { BalenaAPIMock } from '../balena-api-mock';
import { BuilderMock, builderResponsePath } from '../builder-mock';
import { expectStreamNoCRLF, testPushBuildStream } from '../docker-build';
@ -107,12 +106,12 @@ describe('balena push', function () {
it('should create the expected tar stream (single container)', async () => {
const projectPath = path.join(projectsPath, 'no-docker-compose', 'basic');
const isV12W = isWindows && isV12();
const expectedFiles: ExpectedTarStreamFiles = {
'src/.dockerignore': { fileSize: 16, type: 'file' },
'src/start.sh': { fileSize: 89, type: 'file' },
'src/windows-crlf.sh': {
fileSize: isV12W ? 68 : 70,
testStream: isV12W ? expectStreamNoCRLF : undefined,
fileSize: isWindows ? 68 : 70,
testStream: isWindows ? expectStreamNoCRLF : undefined,
type: 'file',
},
Dockerfile: { fileSize: 88, type: 'file' },
@ -124,19 +123,24 @@ describe('balena push', function () {
path.join(builderResponsePath, responseFilename),
'utf8',
);
const expectedResponseLines = [...commonResponseLines[responseFilename]];
const expectedResponseLines = [
...commonResponseLines[responseFilename],
...[
'[Warn] The following .dockerignore file(s) will not be used:',
`[Warn] * ${path.join(projectPath, 'src', '.dockerignore')}`,
'[Warn] Only one .dockerignore file at the source folder (project root) is used.',
'[Warn] Additional .dockerignore files are disregarded. Microservices (multicontainer)',
'[Warn] apps should place the .dockerignore file alongside the docker-compose.yml file.',
'[Warn] See issue: https://github.com/balena-io/balena-cli/issues/1870',
'[Warn] See also CLI v12 release notes: https://git.io/Jf7hz',
'[Warn] -------------------------------------------------------------------------------',
],
];
if (isWindows) {
const fname = path.join(projectPath, 'src', 'windows-crlf.sh');
if (isV12()) {
expectedResponseLines.push(
`[Info] Converting line endings CRLF -> LF for file: ${fname}`,
);
} else {
expectedResponseLines.push(
`[Warn] CRLF (Windows) line endings detected in file: ${fname}`,
'[Warn] Windows-format line endings were detected in some files. Consider using the `--convert-eol` option.',
);
}
expectedResponseLines.push(
`[Info] Converting line endings CRLF -> LF for file: ${fname}`,
);
}
await testPushBuildStream({
@ -154,6 +158,7 @@ describe('balena push', function () {
it('should create the expected tar stream (alternative Dockerfile)', async () => {
const projectPath = path.join(projectsPath, 'no-docker-compose', 'basic');
const expectedFiles: ExpectedTarStreamFiles = {
'src/.dockerignore': { fileSize: 16, type: 'file' },
'src/start.sh': { fileSize: 89, type: 'file' },
'src/windows-crlf.sh': { fileSize: 70, type: 'file' },
Dockerfile: { fileSize: 88, type: 'file' },
@ -165,6 +170,19 @@ describe('balena push', function () {
path.join(builderResponsePath, responseFilename),
'utf8',
);
const expectedResponseLines = [
...commonResponseLines[responseFilename],
...[
'[Warn] The following .dockerignore file(s) will not be used:',
`[Warn] * ${path.join(projectPath, 'src', '.dockerignore')}`,
'[Warn] Only one .dockerignore file at the source folder (project root) is used.',
'[Warn] Additional .dockerignore files are disregarded. Microservices (multicontainer)',
'[Warn] apps should place the .dockerignore file alongside the docker-compose.yml file.',
'[Warn] See issue: https://github.com/balena-io/balena-cli/issues/1870',
'[Warn] See also CLI v12 release notes: https://git.io/Jf7hz',
'[Warn] -------------------------------------------------------------------------------',
],
];
const expectedQueryParams = commonQueryParams.map((i) =>
i[0] === 'dockerfilePath' ? ['dockerfilePath', 'Dockerfile-alt'] : i,
);
@ -174,7 +192,7 @@ describe('balena push', function () {
commandLine: `push testApp -s ${projectPath} -R ${regSecretsPath} --dockerfile Dockerfile-alt --noconvert-eol`,
expectedFiles,
expectedQueryParams,
expectedResponseLines: commonResponseLines[responseFilename],
expectedResponseLines,
projectPath,
responseBody,
responseCode: 200,
@ -183,12 +201,11 @@ describe('balena push', function () {
it('should create the expected tar stream (single container, --[no]convert-eol)', async () => {
const projectPath = path.join(projectsPath, 'no-docker-compose', 'basic');
const eol = isWindows && !isV12();
const expectedFiles: ExpectedTarStreamFiles = {
'src/.dockerignore': { fileSize: 16, type: 'file' },
'src/start.sh': { fileSize: 89, type: 'file' },
'src/windows-crlf.sh': {
fileSize: eol ? 68 : 70,
testStream: eol ? expectStreamNoCRLF : undefined,
fileSize: 70,
type: 'file',
},
Dockerfile: { fileSize: 88, type: 'file' },
@ -200,26 +217,30 @@ describe('balena push', function () {
path.join(builderResponsePath, responseFilename),
'utf8',
);
const expectedResponseLines = [...commonResponseLines[responseFilename]];
const expectedResponseLines = [
...commonResponseLines[responseFilename],
...[
'[Warn] The following .dockerignore file(s) will not be used:',
`[Warn] * ${path.join(projectPath, 'src', '.dockerignore')}`,
'[Warn] Only one .dockerignore file at the source folder (project root) is used.',
'[Warn] Additional .dockerignore files are disregarded. Microservices (multicontainer)',
'[Warn] apps should place the .dockerignore file alongside the docker-compose.yml file.',
'[Warn] See issue: https://github.com/balena-io/balena-cli/issues/1870',
'[Warn] See also CLI v12 release notes: https://git.io/Jf7hz',
'[Warn] -------------------------------------------------------------------------------',
],
];
if (isWindows) {
const fname = path.join(projectPath, 'src', 'windows-crlf.sh');
if (isV12()) {
expectedResponseLines.push(
`[Warn] CRLF (Windows) line endings detected in file: ${fname}`,
'[Warn] Windows-format line endings were detected in some files, but were not converted due to `--noconvert-eol` option.',
);
} else {
expectedResponseLines.push(
`[Info] Converting line endings CRLF -> LF for file: ${fname}`,
);
}
expectedResponseLines.push(
`[Warn] CRLF (Windows) line endings detected in file: ${fname}`,
'[Warn] Windows-format line endings were detected in some files, but were not converted due to `--noconvert-eol` option.',
);
}
await testPushBuildStream({
builderMock: builder,
commandLine: isV12()
? `push testApp -s ${projectPath} -R ${regSecretsPath} --noconvert-eol`
: `push testApp -s ${projectPath} -R ${regSecretsPath} -l`,
commandLine: `push testApp -s ${projectPath} -R ${regSecretsPath} --noconvert-eol`,
expectedFiles,
expectedQueryParams: commonQueryParams,
expectedResponseLines,
@ -269,17 +290,15 @@ describe('balena push', function () {
'utf8',
);
const expectedResponseLines = [
...(isV12()
? [
'[Warn] Using file ignore patterns from:',
`[Warn] ${path.join(projectPath, '.dockerignore')}`,
`[Warn] ${path.join(projectPath, '.gitignore')}`,
`[Warn] ${path.join(projectPath, 'src', '.gitignore')}`,
'[Warn] Note: .gitignore files are being considered because the --gitignore option was',
'[Warn] used. This option is deprecated and will be removed in the next major version',
"[Warn] release. For more information, see 'balena help push'.",
]
: []),
...[
'[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'.",
],
...commonResponseLines[responseFilename],
];
@ -394,12 +413,12 @@ describe('balena push', function () {
const expectedResponseLines = isWindows
? [
'[Warn] Using file ignore patterns from:',
`[Warn] ${path.join(projectPath, '.dockerignore')}`,
'[Warn] The --gitignore option was used, but not .gitignore files were found.',
`[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] with 'docker build'. For more information, see 'balena help push'.",
...commonResponseLines[responseFilename],
]
: commonResponseLines[responseFilename];
@ -425,6 +444,7 @@ describe('balena push', function () {
'service1/Dockerfile.template': { fileSize: 144, type: 'file' },
'service1/file1.sh': { fileSize: 12, type: 'file' },
'service2/Dockerfile-alt': { fileSize: 40, type: 'file' },
'service2/.dockerignore': { fileSize: 14, type: 'file' },
'service2/file2-crlf.sh': {
fileSize: isWindows ? 12 : 14,
testStream: isWindows ? expectStreamNoCRLF : undefined,
@ -439,6 +459,16 @@ describe('balena push', function () {
);
const expectedResponseLines: string[] = [
...commonResponseLines[responseFilename],
...[
'[Warn] The following .dockerignore file(s) will not be used:',
`[Warn] * ${path.join(projectPath, 'service2', '.dockerignore')}`,
'[Warn] Only one .dockerignore file at the source folder (project root) is used.',
'[Warn] Additional .dockerignore files are disregarded. Microservices (multicontainer)',
'[Warn] apps should place the .dockerignore file alongside the docker-compose.yml file.',
'[Warn] See issue: https://github.com/balena-io/balena-cli/issues/1870',
'[Warn] See also CLI v12 release notes: https://git.io/Jf7hz',
'[Warn] -------------------------------------------------------------------------------',
],
];
if (isWindows) {
expectedResponseLines.push(
@ -508,24 +538,16 @@ describe('balena push: project validation', function () {
'basic',
'service1',
);
const expectedErrorLines = isV12()
? [
'Error: "docker-compose.y[a]ml" file found in parent directory: please check that',
"the correct source folder was specified. (Suppress with '--noparent-check'.)",
]
: ['The --nolive flag is only valid when pushing to a local mode device'];
const expectedOutputLines = isV12()
? []
: [
'[Warn] "docker-compose.y[a]ml" file found in parent directory: please check that',
"[Warn] the correct source folder was specified. (Suppress with '--noparent-check'.)",
];
const expectedErrorLines = [
'Error: "docker-compose.y[a]ml" file found in parent directory: please check that',
"the correct source folder was specified. (Suppress with '--noparent-check'.)",
];
const { out, err } = await runCommand(
`push testApp --source ${projectPath} --nolive`,
);
expect(cleanOutput(err, true)).to.include.members(expectedErrorLines);
expect(cleanOutput(out, true)).to.include.members(expectedOutputLines);
expect(out).to.be.empty;
});
it('should suppress a parent folder check with --noparent-check', async () => {

View File

@ -0,0 +1 @@
file2-crlf.sh

View File

@ -0,0 +1 @@
windows-crlf.sh