dockerfilelint
Advanced tools
Comparing version 1.1.3 to 1.2.0
@@ -5,2 +5,13 @@ # Change Log | ||
<a name="1.2.0"></a> | ||
# [1.2.0](https://github.com/replicatedhq/dockerfilelint/compare/v1.1.2...v1.2.0) (2017-07-03) | ||
### Features | ||
* cli can now output json with the `--json` flag ([#76](https://github.com/replicatedhq/dockerfilelint/issues/76)) ([c4b13d2](https://github.com/replicatedhq/dockerfilelint/commit/c4b13d2)) | ||
* support for multiple files on command line ([38f4d72](https://github.com/replicatedhq/dockerfilelint/commit/38f4d72)) | ||
<a name="1.1.2"></a> | ||
@@ -7,0 +18,0 @@ ## 1.1.2 (2016-06-18) |
@@ -70,2 +70,3 @@ var parser = require('./parser'); | ||
} | ||
result.push('deprecated_in_1.13') | ||
@@ -72,0 +73,0 @@ return result; |
@@ -139,5 +139,10 @@ var reference = module.exports = { | ||
'title': 'Missing Arguments', | ||
'description': 'This commands requires additional arguments.', | ||
'description': 'This command requires additional arguments.', | ||
'category': 'Possible Bug' | ||
}, | ||
'deprecated_in_1.13': { | ||
'title': 'Deprecated as of Docker 1.13', | ||
'description': 'This INSTRUCTION is deprecated as of Docker 1.13', | ||
'category': 'Deprecation' | ||
}, | ||
'add_src_invalid': { | ||
@@ -144,0 +149,0 @@ 'title': 'Invalid ADD Source', |
{ | ||
"name": "dockerfilelint", | ||
"version": "1.1.3", | ||
"version": "1.2.0", | ||
"description": "A linter for Dockerfiles to find bugs and encourage best practices", | ||
@@ -37,3 +37,3 @@ "main": "./lib/index.js", | ||
"devDependencies": { | ||
"chai": "^3.5.0", | ||
"chai": "^4.0.1", | ||
"coveralls": "^2.11.6", | ||
@@ -40,0 +40,0 @@ "eslint": "^3.2.2", |
@@ -9,3 +9,3 @@ # Linter and validator for Dockerfile | ||
## Testing | ||
Start unit tests with `npm test` or `yarn run test` | ||
Start unit tests with `npm test`, `yarn run test`, or `docker-compose -f docker-compose.test.yml up` | ||
@@ -18,2 +18,25 @@ ## Running | ||
#### Command Line options | ||
```shell | ||
Usage: dockerfilelint [files | content..] [options] | ||
Options: | ||
-o, --output Specify the format to use for output of linting results. Valid values | ||
are `json` or `cli` (default). [string] | ||
-j, --json Output linting results as JSON, equivalent to `-o json`. [boolean] | ||
-h, --help Show help [boolean] | ||
Examples: | ||
dockerfilelint Dockerfile Lint a Dockerfile in the current working | ||
directory | ||
dockerfilelint test/example/* -j Lint all files in the test/example directory and | ||
output results in JSON | ||
dockerfilelint 'FROM latest' Lint the contents given as a string on the | ||
command line | ||
dockerfilelint < Dockerfile Lint the contents of Dockerfile via stdin | ||
``` | ||
#### Configuring | ||
@@ -55,2 +78,3 @@ You can configure the linter by creating a `.dockerfilelintrc` with the following syntax: | ||
apt-get_missing_rm | ||
deprecated_in_1.13 | ||
``` | ||
@@ -57,0 +81,0 @@ |
@@ -57,6 +57,6 @@ var expect = require('chai').expect | ||
describe("#valid_maintainer(args)", function(){ | ||
it("validates maintainer command has exactly one maintainer", function(){ | ||
expect(checks.valid_maintainer("user <test@gmail.com>")).to.be.empty; | ||
expect(checks.valid_maintainer("user without email")).to.have.length(1); | ||
expect(checks.valid_maintainer("user <test@gmail.com> user2 <test@gmail.com>")).to.have.length(1); | ||
it("validates maintainer command has exactly one maintainer and outputs MAINTAINER is deprecated in 1.13", function(){ | ||
expect(checks.valid_maintainer("user <test@gmail.com>")).to.have.length(1).and.to.eql(['deprecated_in_1.13']); | ||
expect(checks.valid_maintainer("user without email")).to.have.length(2); | ||
expect(checks.valid_maintainer("user <test@gmail.com> user2 <test@gmail.com>")).to.have.length(2); | ||
}); | ||
@@ -63,0 +63,0 @@ }); |
@@ -6,3 +6,3 @@ 'use strict'; | ||
var fs = require('fs'); | ||
var CliReporter = require('../lib/cli_reporter.js'); | ||
var CliReporter = require('../lib/reporter/cli_reporter.js'); | ||
@@ -16,6 +16,6 @@ describe('cli_reporter', () => { | ||
expect(reporter.issueTitleWidth).to.equal(22); | ||
expect(reporter.styles['Deprecation']).to.be.a.function; | ||
expect(reporter.styles['Possible Bug']).to.be.a.function; | ||
expect(reporter.styles['Clarity']).to.be.a.function; | ||
expect(reporter.styles['Optimization']).to.be.a.function; | ||
expect(reporter.styles['Deprecation']).to.be.a('function'); | ||
expect(reporter.styles['Possible Bug']).to.be.a('function'); | ||
expect(reporter.styles['Clarity']).to.be.a('function'); | ||
expect(reporter.styles['Optimization']).to.be.a('function'); | ||
expect(reporter.fileReports).to.be.empty; | ||
@@ -39,147 +39,2 @@ }); | ||
describe('#addFile(file, fileContent, items)', () => { | ||
it('ignores an invalid file argument', () => { | ||
let reporter = new CliReporter().addFile(null); | ||
expect(reporter.fileReports).to.be.empty; | ||
}); | ||
it('adds a good report when no items given', () => { | ||
let file = './test/examples/Dockerfile.busybox'; | ||
let reporter = new CliReporter().addFile(file, fs.readFileSync(file, 'UTF-8'), []); | ||
expect(Object.keys(reporter.fileReports)).to.have.length(1); | ||
let fileReport = reporter.fileReports[file]; | ||
expect(fileReport.itemsByLine).to.be.empty; | ||
expect(fileReport.uniqueIssues).to.equal(0); | ||
expect(fileReport.contentArray).to.have.length(4); | ||
}); | ||
it('modifies existing report when same file added twice', () => { | ||
let file = './test/examples/Dockerfile.registry'; | ||
let fileContent = fs.readFileSync(file, 'UTF-8'); | ||
let item = { | ||
title: 'Consider `--no-install-recommends`', | ||
description: 'Consider using a `--no-install-recommends` when `apt-get` installing packages. This will result in a smaller image size. For\nmore information, see [this blog post](http://blog.replicated.com/2016/02/05/refactoring-a-dockerfile-for-image-size/)', | ||
category: 'Optimization', | ||
line: 5 | ||
}; | ||
let reporter = new CliReporter() | ||
.addFile(file, fileContent, []) | ||
.addFile(file, fileContent, [ item ]); | ||
expect(Object.keys(reporter.fileReports)).to.have.length(1); | ||
let fileReport = reporter.fileReports[file]; | ||
expect(fileReport.uniqueIssues).to.equal(1); | ||
expect(fileReport.contentArray).to.have.length(16); | ||
expect(fileReport.itemsByLine).to.deep.equal({ | ||
'5': [ item ] | ||
}); | ||
}); | ||
it('groups multiple items by line number', () => { | ||
let file = './test/examples/Dockerfile.misc'; | ||
let fileContent = fs.readFileSync(file, 'UTF-8'); | ||
let items = [ | ||
{ | ||
title: 'Base Image Missing Tag', | ||
description: 'Base images should specify a tag to use.', | ||
category: 'Clarity', | ||
line: 5 | ||
}, | ||
{ | ||
title: 'First Command Must Be FROM', | ||
description: 'The first instruction in a Dockerfile must specify the base image using a FROM command. Additionally, FROM cannot appear later in a Dockerfile.', | ||
category: 'Possible Bug', | ||
line: 6 | ||
}, | ||
{ | ||
title: 'Base Image Latest Tag', | ||
description: 'Base images should not use the latest tag.', | ||
category: 'Clarity', | ||
line: 6 | ||
} | ||
]; | ||
let reporter = new CliReporter().addFile(file, fileContent, items); | ||
expect(Object.keys(reporter.fileReports)).to.have.length(1); | ||
let fileReport = reporter.fileReports[file]; | ||
expect(fileReport.uniqueIssues).to.equal(3); | ||
expect(fileReport.contentArray).to.have.length(40); | ||
expect(fileReport.itemsByLine).to.deep.equal({ | ||
'5': [ items[0] ], | ||
'6': items.splice(1) | ||
}); | ||
}); | ||
it('ignores duplicate items', () => { | ||
let file = './test/examples/Dockerfile.misc'; | ||
let fileContent = fs.readFileSync(file, 'UTF-8'); | ||
let items = [ | ||
{ | ||
title: 'First Command Must Be FROM', | ||
description: 'The first instruction in a Dockerfile must specify the base image using a FROM command. Additionally, FROM cannot appear later in a Dockerfile.', | ||
category: 'Possible Bug', | ||
line: 6 | ||
}, | ||
{ | ||
title: 'First Command Must Be FROM', | ||
description: 'The first instruction in a Dockerfile must specify the base image using a FROM command. Additionally, FROM cannot appear later in a Dockerfile.', | ||
category: 'Possible Bug', | ||
line: 6 | ||
} | ||
]; | ||
let reporter = new CliReporter().addFile(file, fileContent, items); | ||
expect(Object.keys(reporter.fileReports)).to.have.length(1); | ||
let fileReport = reporter.fileReports[file]; | ||
expect(fileReport.uniqueIssues).to.equal(1); | ||
expect(fileReport.contentArray).to.have.length(40); | ||
expect(fileReport.itemsByLine).to.deep.equal({ | ||
'6': [ items[0] ] | ||
}); | ||
}); | ||
it('allows multiple files to be added', () => { | ||
let file1 = './test/examples/Dockerfile.registry'; | ||
let file1Content = fs.readFileSync(file1, 'UTF-8'); | ||
let file1Items = [ | ||
{ | ||
title: 'Consider `--no-install-recommends`', | ||
description: 'Consider using a `--no-install-recommends` when `apt-get` installing packages. This will result in a smaller image size. For\nmore information, see [this blog post](http://blog.replicated.com/2016/02/05/refactoring-a-dockerfile-for-image-size/)', | ||
category: 'Optimization', | ||
line: 5 | ||
} | ||
]; | ||
let file2 = './test/examples/Dockerfile.misc'; | ||
let file2Content = fs.readFileSync(file2, 'UTF-8'); | ||
let file2Items = [ | ||
{ | ||
title: 'Base Image Missing Tag', | ||
description: 'Base images should specify a tag to use.', | ||
category: 'Clarity', | ||
line: 5 | ||
}, | ||
{ | ||
title: 'First Command Must Be FROM', | ||
description: 'The first instruction in a Dockerfile must specify the base image using a FROM command. Additionally, FROM cannot appear later in a Dockerfile.', | ||
category: 'Possible Bug', | ||
line: 6 | ||
} | ||
]; | ||
let reporter = new CliReporter() | ||
.addFile(file1, file1Content, file1Items) | ||
.addFile(file2, file2Content, file2Items); | ||
expect(Object.keys(reporter.fileReports)).to.have.length(2); | ||
let file1Report = reporter.fileReports[file1]; | ||
expect(file1Report.uniqueIssues).to.equal(1); | ||
expect(file1Report.contentArray).to.have.length(16); | ||
expect(file1Report.itemsByLine).to.deep.equal({ | ||
'5': file1Items | ||
}); | ||
let file2Report = reporter.fileReports[file2]; | ||
expect(file2Report.uniqueIssues).to.equal(2); | ||
expect(file2Report.contentArray).to.have.length(40); | ||
expect(file2Report.itemsByLine).to.deep.equal({ | ||
'5': [ file2Items[0] ], | ||
'6': [ file2Items[1] ] | ||
}); | ||
}); | ||
}); | ||
describe('#buildReport()', () => { | ||
@@ -201,3 +56,3 @@ it('returns blank report if no files added', () => { | ||
'File: ' + file, | ||
'Issues: \u001b[32mNone found\u001b[39m 👍', | ||
'Issues: ' + chalk.green('None found') + ' 👍', | ||
'' | ||
@@ -204,0 +59,0 @@ ]); |
@@ -32,4 +32,4 @@ var expect = require('chai').expect | ||
describe("#nginx", function(){ | ||
it("validates the nginx Dockerfile has 1 issue (known issue)", function(){ | ||
expect(dockerfilelint.run('./test/examples', fs.readFileSync('./test/examples/Dockerfile.nginx', 'UTF-8'))).to.have.length(1); | ||
it("validates the nginx Dockerfile has 2 issue (known issue)", function(){ | ||
expect(dockerfilelint.run('./test/examples', fs.readFileSync('./test/examples/Dockerfile.nginx', 'UTF-8'))).to.have.length(2); | ||
}); | ||
@@ -116,2 +116,5 @@ }); | ||
line: 9 }, | ||
{ title: 'Deprecated as of Docker 1.13', | ||
rule: 'deprecated_in_1.13', | ||
line: 9 }, | ||
{ title: 'Missing Required Arguments', | ||
@@ -118,0 +121,0 @@ rule: 'required_params', |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
186080
49
1871
170
5
1