forked from todogroup/repolinter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrepolinter.js
executable file
·151 lines (150 loc) · 4.99 KB
/
repolinter.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/usr/bin/env node
// Copyright 2017 TODO Group. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
const path = require('path')
const repolinter = require('..')
const rimraf = require('rimraf')
const git = require('simple-git/promise')()
/** @type {any} */
const fetch = require('node-fetch')
const fs = require('fs')
const os = require('os')
const yaml = require('js-yaml')
// eslint-disable-next-line no-unused-expressions
require('yargs')
.command(
['lint [directory]', '*'],
'run repolinter on the specified directory, outputting results to STDOUT.',
yargs => {
yargs
.positional('directory', {
describe: 'The target directory to lint',
default: './',
type: 'string'
})
.option('dryRun', {
alias: 'd',
describe:
'Prevents repolinter from making any modifications to disk, instead generating a report of suggested modifications.',
default: false,
type: 'boolean'
})
.option('allowPaths', {
alias: 'a',
describe:
'Limits repolinter to the specified list of directories (directories must still be contained in the target directory).',
default: [],
type: 'array'
})
.option('rulesetFile', {
alias: 'r',
describe:
'Specify an alternate location for the repolinter configuration to use (This will default to repolinter.json/repolinter.yaml at the root of the project, or the internal default ruleset if none is found).',
type: 'string'
})
.option('rulesetUrl', {
alias: 'u',
describe:
'Specify an alternate URL repolinter configuration to use (This will default to repolinter.json/repolinter.yaml at the root of the project, or the internal default ruleset if none is found).',
type: 'string'
})
.option('git', {
alias: 'g',
describe:
'Lint a git repository instead of a directory. The URL specified in the directory parameter will be cloned into a temporary directory in order for repolinter to process it.',
default: false,
type: 'boolean'
})
.option('format', {
alias: 'f',
describe:
'Specify the formatter to use for the output ("json", "markdown", or "console")',
default: 'console',
type: 'string'
})
},
async (/** @type {any} */ argv) => {
let rulesetParsed = null
let jsonerror
let yamlerror
// resolve the ruleset if a url is specified
if (argv.rulesetUrl) {
const res = await fetch(argv.rulesetUrl)
if (!res.ok) {
console.error(
`Failed to fetch config from ${argv.rulesetUrl} with status code ${res.status}`
)
process.exitCode = 1
return
}
const data = await res.text()
// attempt to parse as JSON
try {
rulesetParsed = JSON.parse(data)
} catch (e) {
jsonerror = e
}
// attempt to parse as YAML
if (!rulesetParsed) {
try {
rulesetParsed = yaml.safeLoad(data)
} catch (e) {
yamlerror = e
}
}
// throw an error if neither worked
if (!rulesetParsed) {
console.log(`Failed to fetch ruleset from URL ${argv.rulesetUrl}:`)
console.log(
`\tJSON failed with error ${jsonerror && jsonerror.toString()}`
)
console.log(
`\tYAML failed with error ${yamlerror && yamlerror.toString()}`
)
process.exitCode = 1
return
}
}
let tmpDir = null
// temporarily clone a git repo to lint
if (argv.git) {
tmpDir = await fs.promises.mkdtemp(
path.join(os.tmpdir(), 'repolinter-')
)
const result = await git.clone(argv.directory, tmpDir)
if (result) {
console.error(result)
process.exitCode = 1
rimraf(tmpDir, () => {})
return
}
}
// run the linter
const output = await repolinter.lint(
tmpDir || path.resolve(process.cwd(), argv.directory),
argv.allowPaths,
rulesetParsed || argv.rulesetFile,
argv.dryRun
)
// create the output
let formatter
if (argv.format && argv.format.toLowerCase() === 'json') {
formatter = repolinter.jsonFormatter
} else if (argv.format && argv.format.toLowerCase() === 'markdown') {
formatter = repolinter.markdownFormatter
} else {
formatter = repolinter.defaultFormatter
}
const formattedOutput = formatter.formatOutput(output, argv.dryRun)
// log it!
console.log(formattedOutput)
process.exitCode = output.passed ? 0 : 1
// delete the tmpdir if it exists
if (tmpDir) {
rimraf(tmpDir, function () {})
}
}
)
.demandCommand()
.help()
.strict().argv // eslint-disable-line