Skip to content

Commit

Permalink
feat: environment flag to check all licenses (#23)
Browse files Browse the repository at this point in the history
feat: non-production dependency checking

Co-authored-by: Bradley Priest <bradleypriest@gmail.com>
  • Loading branch information
kingnebby and bradleypriest committed Aug 23, 2020
1 parent 2075e6c commit 46d4ed9
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 23 deletions.
24 changes: 13 additions & 11 deletions src/checker.ts
Expand Up @@ -48,12 +48,13 @@ export function isLicenseValidByConfig(configLicenses, license): boolean {
* }
* }
*/
export async function generateLicensesMap() {
const opts = {
start: "./",
production: true,
export async function generateLicensesMap(opts: any = {}) {
opts = {
...defaultLicenseInitOpts,
...opts,
summary: true
}

const dependencies = await init(opts)
const licenses = {}
const unprocessedLicenseEntries = {}
Expand Down Expand Up @@ -165,8 +166,8 @@ export async function getDependencies(opts = {}) {
}

// Updates existing licenses based on user input and existing dependencies
export async function getUserLicenseInput(existingLicenses) {
const { licenses: licenseMap } = await generateLicensesMap()
export async function getUserLicenseInput(existingLicenses, licenseInitOpts) {
const { licenses: licenseMap } = await generateLicensesMap(licenseInitOpts)
const approvedLicenses = [...existingLicenses]
for (const licenseName in licenseMap) {
if (!existingLicenses.includes(licenseName)) {
Expand All @@ -188,8 +189,9 @@ export async function getUserLicenseInput(existingLicenses) {
return approvedLicenses
}

export async function getUserModulesInput(existingLicenses, existingModules) {
export async function getUserModulesInput(existingLicenses, existingModules, licenseInitOpts) {
const dependencies = await getDependencies({
...licenseInitOpts,
summary: true
})
const unallowedDependencyMap = await getUnallowedDependencies(
Expand Down Expand Up @@ -235,12 +237,12 @@ export async function getUserModulesInput(existingLicenses, existingModules) {
}

// Shows all the licenses in use for each module.
export async function summary(filePath) {
export async function summary(filePath, licenseInitOpts) {
const currentConfig = await getAndValidateConfig(filePath)
const {
licenses: licenseMap,
unprocessedLicenseEntries
} = await generateLicensesMap()
} = await generateLicensesMap(licenseInitOpts)
const summary = {
approved: {},
unapproved: {},
Expand Down Expand Up @@ -345,8 +347,8 @@ export function pruneTreeByLicenses(name, node, invalidLicensedModules) {
}

// Main method that initiates the checking process
export async function getInvalidModuleDependencyTree(config) {
const licenses = await getDependencies()
export async function getInvalidModuleDependencyTree(config, licenseInitOpts) {
const licenses = await getDependencies(licenseInitOpts)
const invalidLicensedModules = getInvalidModules(licenses, config)
if (invalidLicensedModules === undefined) {
return
Expand Down
31 changes: 26 additions & 5 deletions src/index.ts
Expand Up @@ -21,16 +21,33 @@ program
.version(pkg.version, "-v, --version")
.option("--summary", "Prints a summary report")
.option("-i, --interactive", "Runs in interactive mode.")
.option(
"--environment [environment]",
"Which dependencies to check. (production, all)",
"production"
)
.option(
"-m, --modules-only",
"Modifies module white list if in interactive mode."
)

// Default Action
async function action(args: program.Command): Promise<void> {
let defaultLicenseInitOpts = {}

switch (args.environment) {
case "all":
defaultLicenseInitOpts = {
production: undefined
}
break
default:
break
}

const fileName = ".approved-licenses.yml"
if (args.summary) {
const summaryMap = await summary(fileName)
const summaryMap = await summary(fileName, defaultLicenseInitOpts)
const prettySummaryMap = prettySummary(summaryMap)
console.log(prettySummaryMap)
if (_.isEmpty(summaryMap.approved)) {
Expand All @@ -44,11 +61,15 @@ async function action(args: program.Command): Promise<void> {
if (args.interactive) {
const yamlObj = await getAndValidateConfig(fileName)
if (!args.modulesOnly) {
yamlObj.licenses = await getUserLicenseInput(yamlObj.licenses)
yamlObj.licenses = await getUserLicenseInput(
yamlObj.licenses,
defaultLicenseInitOpts
)
}
yamlObj.modules = await getUserModulesInput(
yamlObj.licenses,
yamlObj.modules
yamlObj.modules,
defaultLicenseInitOpts
)
await writeConfig(fileName, yamlObj)
}
Expand All @@ -70,10 +91,10 @@ async function action(args: program.Command): Promise<void> {
process.exit(1)
}

const depTree = (await getInvalidModuleDependencyTree(parsedConfig)) as any
const depTree = (await getInvalidModuleDependencyTree(parsedConfig, defaultLicenseInitOpts)) as any

if (!_.isEmpty(depTree)) {
const summaryMap = await summary(fileName)
const summaryMap = await summary(fileName, defaultLicenseInitOpts)
const prettySummaryMap = prettySummary(summaryMap)
console.log(prettySummaryMap)
console.log(`UNAPPROVED MODULES:`)
Expand Down
59 changes: 52 additions & 7 deletions test/integ/cli.spec.ts
Expand Up @@ -60,31 +60,37 @@ function no(cp) {
}

function isAllowLicensePrompt(buffer) {
return !!// caste to boolean
return !!(
// caste to boolean
buffer
.toString("utf8")
.replace(/\n/g, "") // new lines cause problems
.match(/.*Would you like to allow this license\?.*\(Use arrow keys\)/m) // only works if initial prompt is unique
.match(/.*Would you like to allow this license\?.*\(Use arrow keys\)/m)
) // only works if initial prompt is unique
}

function isModifyModulesPrompt(buffer) {
return !!// caste to boolean
return !!(
// caste to boolean
buffer
.toString("utf8")
.replace(/\n/g, "") // new lines cause problems
.match(
/.*Would you like to modify your approved module list\?.*\(Use arrow keys\)/m
) // only works if initial prompt is unique
)
) // only works if initial prompt is unique
}

function isAllowModulePrompt(buffer) {
return !!// caste to boolean
return !!(
// caste to boolean
buffer
.toString("utf8")
.replace(/\n/g, "") // new lines cause problems
.match(
/.*Would you like to allow this module anyway\?.*\(Use arrow keys\)/m
) // only works if initial prompt is unique
)
) // only works if initial prompt is unique
}

// Allows the integration test to run on this repo's package.json and installed modules.
Expand Down Expand Up @@ -126,13 +132,52 @@ describe("integration test: validates current repo is in a valid state", () => {
expect(stdout.toString("utf-8")).to.equal(expectedResult)
}).timeout(20000)

it("should support fetching all licenses", async () => {
const expectedResult = [
`Licenses`,
"",
"APPROVED:",
"├─ MIT: 482",
"├─ ISC: 81",
"├─ BSD-2-Clause: 14",
"├─ Apache-2.0: 18",
"├─ BSD-3-Clause: 20",
"├─ CC-BY-3.0: 1",
"├─ CC0-1.0: 1",
"├─ (MIT AND CC-BY-3.0): 1",
"└─ (MIT OR CC0-1.0): 1",
"",
"UNAPPROVED:",
"├─ (MIT OR Apache-2.0): 1",
"├─ BSD: 1",
"├─ BSD*: 1",
"├─ MIT*: 1",
"├─ (WTFPL OR MIT): 1",
"├─ Apache License, Version 2.0: 2",
"└─ Unlicense: 1",
"",
"UNPROCESSED:",
"└─ json-schema@0.2.3",
" ├─ 0: AFLv2.1",
" └─ 1: BSD",
"",
""
].join("\n")
let { stdout } = spawnSync(
"ts-node",
["./src/index.ts", "--summary", "--environment=all"],
{}
)
expect(stdout.toString("utf8")).to.equal(expectedResult)
}).timeout(20000)

it("should print summary", async () => {
const expectedResult = [
`Licenses`,
"",
"APPROVED:",
"├─ ISC: 24",
"├─ MIT: 60",
"├─ MIT: 59",
"├─ BSD-2-Clause: 2",
"├─ BSD-3-Clause: 2",
"├─ Apache-2.0: 4",
Expand Down

0 comments on commit 46d4ed9

Please sign in to comment.