Skip to content

Commit

Permalink
feat: add snyk ignore command
Browse files Browse the repository at this point in the history
  • Loading branch information
aviadatsnyk committed Apr 4, 2017
1 parent d78693d commit e5fb843
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 7 deletions.
3 changes: 2 additions & 1 deletion cli/args.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ function args(processargv) {
command === 'modules' ||
command === 'scenario' ||
command === 'monitor' ||
command === 'wizard') {
command === 'wizard' ||
command === 'ignore') {
// copy all the options across to argv._ as an object
argv._.push(argv);
}
Expand Down
46 changes: 46 additions & 0 deletions cli/commands/ignore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
module.exports = ignore;

var debug = require('debug')('snyk');
var policy = require('snyk-policy');
var Promise = require('es6-promise').Promise; // jshint ignore:line

function ignore(options) {
debug('snyk ignore called with options: %O', options);
if (!options.id) {
return Promise.reject(Error('idRequired'));
}
options.expiry = new Date(options.expiry);
if (options.expiry.getTime() !== options.expiry.getTime()) {
debug('No/invalid expiry given, using the default 30 days');
options.expiry = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000);
}
if (!options.reason) {
options.reason = 'None Given';
}
if (!options.path) {
debug('using cwd() as path');
options.path = process.cwd();
}

debug('changing policy: ignore "%s", for all paths, reason: "%s", until: %o',
options.id, options.reason, options.expiry);
return policy.load(options.path)
.catch(function (error) {
if (error.code === 'ENOENT') { // file does not exist - create it
return policy.create();
}
throw Error('policyFile');
})
.then(function ignoreIssue(pol) {
pol.ignore[options.id] = [
{
'*':
{
reason: options.reason,
expires: options.expiry,
},
},
];
policy.save(pol, options.path);
});
}
11 changes: 6 additions & 5 deletions cli/commands/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@ require('../../lib/spinner').isRequired = false;
// time as low as possible

var commands = {
help: hotload('./help'),
auth: hotload('./auth'),
version: hotload('./version'),
config: hotload('./config'),
help: hotload('./help'),
ignore: hotload('./ignore'),
modules: hotload('./modules'),
monitor: hotload('./monitor'),
test: hotload('./test'),
policy: hotload('./policy'),
protect: hotload('./protect'),
wizard: hotload('./protect/wizard'),
modules: hotload('./modules'),
scenario: hotload('./scenario'),
test: hotload('./test'),
'test-unpublished': hotload('./unpublished'),
version: hotload('./version'),
wizard: hotload('./protect/wizard'),
};
commands.aliases = abbrev(Object.keys(commands));
commands.aliases.t = 'test';
Expand Down
1 change: 1 addition & 0 deletions help/help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Commands:
monitor ............ Record the state of dependencies and any
vulnerabilities on snyk.io.
policy ............. Display the Snyk policy for a package.
ignore ............. Ignore an issue. For more help run `snyk help ignore`.

Options:

Expand Down
16 changes: 16 additions & 0 deletions help/ignore.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

Ignore:

$ snyk ignore --id=IssueID [--expiry=expiry] [--reason='reason for ignoring']

Ignore a certain issue, according to its snyk ID for all occurrences.

Options:

id ................. snyk ID for the issue to ignore. Required.
expiry ............. expiry date string, according to RFC2822 (https://tools.ietf.org/html/rfc2822#page-14)
reason ............. the reason to ignore this issue

Examples:

$ snyk ignore --id='npm:qs:20170213' --expiry='2017-03-30' --reason='testing'
3 changes: 3 additions & 0 deletions lib/error.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ var errors = {
'and try again.',
timeout: 'The request has timed out on the server side.\nPlease re-run ' +
'this command with the `-d` flag and send the output to support@snyk.io.',
policyFile: 'Bad policy file, please use --path=PATH to specify a ' +
'directory with a .snyk file',
idRequired: 'id is a required field for `snyk ignore`',
};

// a key/value pair of error.code (or error.message) as the key, and our nice
Expand Down
53 changes: 53 additions & 0 deletions test/cli.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ var port = process.env.PORT = process.env.SNYK_PORT = 12345;
var sinon = require('sinon');
var proxyquire = require('proxyquire');
var parse = require('url').parse;
var policy = require('snyk-policy');

process.env.SNYK_API = 'http://localhost:' + port + '/api/v1';
process.env.SNYK_HOST = 'http://localhost:' + port;
Expand Down Expand Up @@ -144,6 +145,58 @@ test('auth via github', function (t) {
});
});

test('snyk ignore - all options', function (t) {
t.plan(1);
var fullPolicy = {ID: [
{'*': {
reason: 'REASON',
expires: new Date('2017-10-07T00:00:00.000Z'), },
},
],
};
var dir = testUtils.tmpdir();
cli.ignore({
id: 'ID', reason: 'REASON', expiry: new Date('2017-10-07'), path: dir,
}).catch(() => t.fail('ignore should succeed'))
.then(() => policy.load(dir))
.then(pol => {
t.deepEquals(pol.ignore, fullPolicy, 'policy written correctly');
});
});

test('snyk ignore - no ID', function (t) {
t.plan(1);
var dir = testUtils.tmpdir();
cli.ignore({
reason: 'REASON', expiry: new Date('2017-10-07'), path: dir,
}).then(function (res) {
t.fail('should not succeed with missing ID');
}).catch(function (e) {
var errors = require('../lib/error');
var message = chalk.stripColor(errors.message(e));
t.equal(message.toLowerCase().indexOf('id is a required field'), 0,
'captured failed ignore (no --id given)');
});
});

test('snyk ignore - default options', function (t) {
t.plan(3);
var dir = testUtils.tmpdir();
cli.ignore({id: 'ID3', path: dir,
}).catch(() => t.fail('ignore should succeed'))
.then(() => policy.load(dir))
.then(pol => {
t.true(pol.ignore.ID3, 'policy ID written correctly');
t.is(pol.ignore.ID3[0]['*'].reason, 'None Given',
'policy (default) reason written correctly');
var expiryFromNow = pol.ignore.ID3[0]['*'].expires - Date.now();
// not more than 30 days ahead, not less than (30 days - 1 minute)
t.true(expiryFromNow <= 30 * 24 * 60 * 60 * 1000 &&
expiryFromNow >= 30 * 24 * 59 * 60 * 1000,
'policy (default) expiry wirtten correctly');
});
});

after('teardown', function (t) {
t.plan(4);

Expand Down
14 changes: 13 additions & 1 deletion test/utils.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
module.exports = {
silenceLog: silenceLog,
extendExpiries: extendExpiries,
tmpdir: tmpdir,
};

var osTmpdir = require('os').tmpdir;
var join = require('path').join;
var mkdirSync = require('fs').mkdirSync;

function silenceLog() {
var old = console.log;

Expand All @@ -21,4 +26,11 @@ function extendExpiries(policy) {
rule[path].expires = d;
});
});
}
}

function tmpdir() {
var dirname = join(osTmpdir(), 'TMP' + Math.random().toString(36)
.replace(/[^a-z0-9]+/g, '').substr(2, 12));
mkdirSync(dirname);
return dirname;
}

0 comments on commit e5fb843

Please sign in to comment.