Skip to content

Commit

Permalink
feat: add -p flag to dependency-check to only check production deps
Browse files Browse the repository at this point in the history
Adds a convenience flag to only check for missing production deps.

Also allows the user to pass files to check instead of always using
the defaults.

Also, also fixes the spinner when dep-checks fail so the formatting of the
error message isn't all kinds of messed up.

Would have caught ipfs/js-ipfs#3393
  • Loading branch information
achingbrain committed Nov 13, 2020
1 parent 3edd1d4 commit de08f3a
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 16 deletions.
27 changes: 23 additions & 4 deletions cmds/z-dependency-check.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,37 @@ const EPILOG = `
Supports options forwarding with '--' for more info check https://github.com/maxogden/dependency-check#cli-usage
`

const commandName = depCheck.commandNames[0]

module.exports = {
command: 'dependency-check',
aliases: ['dep-check', 'dep'],
command: `${commandName} [input...]`,
aliases: depCheck.commandNames.filter(name => name === commandName),
desc: 'Run `dependency-check` cli with aegir defaults.',
builder: (yargs) => {
yargs
.epilog(EPILOG)
.example('aegir dependency-check -- --unused', 'To check unused packages in your repo.')
.positional('input', {
describe: 'Files to check',
type: 'array',
default: depCheck.defaultInput
})
.option('p', {
alias: 'production-only',
describe: 'Check production dependencies and paths only',
type: 'boolean',
default: false
})
},
async handler (argv) {
const spinner = ora('Checking dependencies').start()
await depCheck(argv)
spinner.succeed()

try {
await depCheck(argv, process.argv)
spinner.succeed()
} catch (err) {
spinner.fail()
throw err
}
}
}
59 changes: 55 additions & 4 deletions src/dependency-check.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,69 @@ const defaultInput = [
'!./test/fixtures/**/*.js'
]

const commandNames = ['dependency-check', 'dep-check', 'dep']

/**
* Returns true if the user invoked the command with non-flag or
* optional args
*
* @param {Array} args - process.argv or similar
* @returns {boolean} - true if the user passed files as positional arguments
*/
const hasPassedFileArgs = (args) => {
let foundCommand = false

for (let i = 0; i < args.length; i++) {
const arg = args[i]

if (arg === '--') {
// reached forward args
break
}

if (foundCommand && !arg.startsWith('-')) {
// was not a flag (e.g. -f) or option (e.g. --foo)
return true
}

if (commandNames.includes(arg)) {
foundCommand = true
}
}

return false
}

/**
* Check dependencies
*
* @param {object} argv - Command line arguments passed to the process.
* @param {Array} processArgs - Unparsed command line arguments used to start the process
* @param {ExecaOptions} execaOptions - execa options.
* @returns {ExecaChildProcess} - Child process that does dependency check.
*/
const check = (argv = { _: [] }, execaOptions) => {
const input = argv._.slice(1)
const check = (argv = { _: [], input: [] }, processArgs = [], execaOptions) => {
const forwardOptions = argv['--'] ? argv['--'] : []
const defaults = input.length ? input : defaultInput
let input = argv.input

if (argv.productionOnly) {
if (!hasPassedFileArgs(processArgs)) {
input = [
'package.json',
'./src/**/*.js'
]
}

forwardOptions.push('--no-dev')
}

if (input.length === 0) {
input = defaultInput
}

return execa('dependency-check',
[
...defaults,
...input,
'--missing',
...forwardOptions
],
Expand All @@ -42,3 +91,5 @@ const check = (argv = { _: [] }, execaOptions) => {
}

module.exports = check
module.exports.defaultInput = defaultInput
module.exports.commandNames = commandNames
43 changes: 36 additions & 7 deletions test/dependency-check.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,49 @@ const path = require('path')

describe('dependency check', () => {
it('should fail for missing deps', async () => {
await expect(check(undefined, {
await expect(check(undefined, [], {
cwd: path.join(__dirname, 'fixtures/dependency-check/fail')
})).to.eventually.rejectedWith('execa')
})).to.eventually.be.rejectedWith('execa')
})

it('should pass when theres no missing deps', async () => {
await expect(check(undefined, {
it('should pass when there are no missing deps', async () => {
await expect(check(undefined, [], {
cwd: path.join(__dirname, 'fixtures/dependency-check/pass')
})).to.eventually.fulfilled()
})).to.eventually.be.fulfilled()
})

it('should forward options', async () => {
await expect(check({ _: [], '--': ['--unused'] }, {
await expect(check({ _: [], '--': ['--unused'], input: [] }, [], {
cwd: path.join(__dirname, 'fixtures/dependency-check/pass')
})).to.eventually.rejectedWith('Modules in package.json not used in code: pico')
})).to.eventually.be.rejectedWith('Modules in package.json not used in code: pico')
})

it('should fail for missing production deps', async () => {
await expect(check({ productionOnly: true, input: [] }, [], {
cwd: path.join(__dirname, 'fixtures/dependency-check/fail-prod')
})).to.eventually.be.rejectedWith('execa')
})

it('should pass for passed files', async () => {
await expect(check({
input: [
'derp/foo.js'
]
}, [], {
cwd: path.join(__dirname, 'fixtures/dependency-check/pass-certain-files')
})).to.eventually.be.fulfilled()
})

it('should pass for passed production files', async () => {
await expect(check({
productionOnly: true,
input: [
'derp/foo.js'
]
}, [
'node', 'aegir', 'dependency-check', 'derp/foo.js'
], {
cwd: path.join(__dirname, 'fixtures/dependency-check/pass-certain-files')
})).to.eventually.be.fulfilled()
})
})
3 changes: 3 additions & 0 deletions test/fixtures/dependency-check/fail-prod/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'use strict'
/* eslint-disable no-unused-vars */
const execa = require('execa')
8 changes: 8 additions & 0 deletions test/fixtures/dependency-check/fail-prod/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "dep-check-fail-prod",
"version": "1.0.0",
"main": "index.js",
"devDependencies": {
"execa": "1.0.0"
}
}
3 changes: 3 additions & 0 deletions test/fixtures/dependency-check/pass-certain-files/derp/foo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'use strict'
/* eslint-disable no-unused-vars */
const execa = require('execa')
3 changes: 3 additions & 0 deletions test/fixtures/dependency-check/pass-certain-files/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'use strict'
/* eslint-disable no-unused-vars */
const pico = require('pico')
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "dep-check-pass",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"execa": "1.0.0"
}
}
1 change: 0 additions & 1 deletion test/fixtures/dependency-check/pass/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@
"pico": "1.0.0"
}
}

0 comments on commit de08f3a

Please sign in to comment.