-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
356 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
{ | ||
"plugins": ["lerna"], | ||
"plugins": ["lerna", "license"], | ||
"exec": { | ||
"before_commit": "yarn run build" | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#!/bin/bash | ||
|
||
# | ||
# Small helper to create a new plugin skeleton | ||
# | ||
|
||
name="$1" | ||
Name="${name^}" | ||
|
||
cp -r packages/plugin-template "packages/plugin-$name" | ||
cd "packages/plugin-$name" | ||
rm -rf build | ||
rm *.tsbuildinfo | ||
|
||
sed -i "s/template/$name/g" package.json | ||
sed -i '/ "private": true,/d' package.json | ||
sed -i "s/template/$name/g" src/index.ts | ||
sed -i "s/Template/$Name/g" src/index.ts | ||
sed -i "s/Template/$Name/g" src/index.test.ts | ||
|
||
cd ../.. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
{ | ||
"name": "@alcalzone/release-script-plugin-license", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"version": "3.0.0", | ||
"description": "Plugin for Al Calzone's release script: license", | ||
"keywords": [], | ||
"license": "MIT", | ||
"author": { | ||
"name": "AlCalzone", | ||
"email": "[email protected]" | ||
}, | ||
"main": "build/index.js", | ||
"exports": { | ||
".": "./build/index.js", | ||
"./package.json": "./package.json", | ||
"./*.map": "./build/*.js.map", | ||
"./*": "./build/*.js" | ||
}, | ||
"types": "build/index.d.ts", | ||
"typesVersions": { | ||
"*": { | ||
"build/index.d.ts": [ | ||
"build/index.d.ts" | ||
], | ||
"*": [ | ||
"build/*" | ||
] | ||
} | ||
}, | ||
"files": [ | ||
"build/", | ||
"LICENSE" | ||
], | ||
"engines": { | ||
"node": ">=12.20" | ||
}, | ||
"dependencies": { | ||
"@alcalzone/release-script-core": "3.0.0", | ||
"fs-extra": "^10.0.0", | ||
"tiny-glob": "^0.2.9" | ||
}, | ||
"devDependencies": { | ||
"@alcalzone/release-script-testing": "3.0.0", | ||
"jest-extended": "^0.11.5", | ||
"typescript": "*" | ||
}, | ||
"scripts": { | ||
"clean": "tsc -b tsconfig.build.json --clean", | ||
"build": "tsc -b tsconfig.build.json", | ||
"watch": "tsc -b tsconfig.build.json --watch" | ||
}, | ||
"homepage": "https://github.com/AlCalzone/release-script/tree/main/packages/plugin-license#readme", | ||
"repository": { | ||
"type": "git", | ||
"url": "[email protected]:AlCalzone/release-script.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/AlCalzone/release-script/issues" | ||
}, | ||
"readmeFilename": "README.md" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import { DefaultStages } from "@alcalzone/release-script-core"; | ||
import { createMockContext, TestFS } from "@alcalzone/release-script-testing"; | ||
import LicensePlugin from "."; | ||
|
||
describe("License plugin", () => { | ||
describe("check stage", () => { | ||
let testFS: TestFS; | ||
let testFSRoot: string; | ||
beforeEach(async () => { | ||
testFS = new TestFS(); | ||
testFSRoot = await testFS.getRoot(); | ||
}); | ||
afterEach(async () => { | ||
await testFS.remove(); | ||
}); | ||
|
||
it("errors when the copyright year is outdated (Test 1)", async () => { | ||
const licPlugin = new LicensePlugin(); | ||
const context = createMockContext({ | ||
plugins: [licPlugin], | ||
cwd: testFSRoot, | ||
argv: { | ||
license: ["{LICENSE,README}{,.md}"], | ||
}, | ||
}); | ||
|
||
await testFS.create({ | ||
"README.md": `## License | ||
Apache 2.0 Copyright 2018-2020`, | ||
}); | ||
|
||
await licPlugin.executeStage(context, DefaultStages.check); | ||
expect(context.errors).toContainEqual(expect.stringMatching("outdated copyright year")); | ||
expect(context.errors).toContainEqual(expect.stringMatching("2018-2020")); | ||
}); | ||
|
||
it("errors when the copyright year is outdated (Test 2)", async () => { | ||
const licPlugin = new LicensePlugin(); | ||
const context = createMockContext({ | ||
plugins: [licPlugin], | ||
cwd: testFSRoot, | ||
argv: { | ||
license: ["{LICENSE,README}{,.md}"], | ||
}, | ||
}); | ||
|
||
await testFS.create({ | ||
"LICENSE.md": `Copyright 2018 [email protected]`, | ||
}); | ||
|
||
await licPlugin.executeStage(context, DefaultStages.check); | ||
expect(context.errors).toContainEqual(expect.stringMatching("outdated copyright year")); | ||
expect(context.errors).toContainEqual(expect.stringMatching("2018")); | ||
}); | ||
|
||
it("errors when the copyright year is outdated (Test 3)", async () => { | ||
const licPlugin = new LicensePlugin(); | ||
const context = createMockContext({ | ||
plugins: [licPlugin], | ||
cwd: testFSRoot, | ||
argv: { | ||
license: ["{LICENSE,README}{,.md}"], | ||
}, | ||
}); | ||
|
||
await testFS.create({ | ||
LICENSE: `Copyright (C) 2018 - 2019 [email protected]`, | ||
"README.md": `Copyright 2017 [email protected]`, | ||
}); | ||
|
||
await licPlugin.executeStage(context, DefaultStages.check); | ||
expect(context.errors).toContainEqual(expect.stringMatching("outdated copyright year")); | ||
expect(context.errors).toContainEqual(expect.stringMatching("2018 - 2019")); | ||
expect(context.errors).toContainEqual(expect.stringMatching("2017")); | ||
}); | ||
|
||
it("errors when the copyright year is outdated (Test 3)", async () => { | ||
const licPlugin = new LicensePlugin(); | ||
const context = createMockContext({ | ||
plugins: [licPlugin], | ||
cwd: testFSRoot, | ||
argv: { | ||
license: ["packages/**/{LICENSE,README}{,.md}"], | ||
}, | ||
}); | ||
|
||
await testFS.create({ | ||
"packages/p1/LICENSE": `Copyright ${new Date().getFullYear()} is ok`, | ||
"packages/p2/README.md": `Copyright 2017 [email protected]`, | ||
}); | ||
|
||
await licPlugin.executeStage(context, DefaultStages.check); | ||
expect(context.errors).toContainEqual( | ||
expect.stringMatching(/packages[\\/]p2[\\/]README.md/i), | ||
); | ||
expect(context.errors).not.toContainEqual( | ||
expect.stringMatching(/packages[\\/]p1[\\/]LICENSE/i), | ||
); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { DefaultStages } from "@alcalzone/release-script-core"; | ||
import type { Context, Plugin, Stage } from "@alcalzone/release-script-core/types"; | ||
import fs from "fs-extra"; | ||
import path from "path"; | ||
import glob from "tiny-glob"; | ||
import type { Argv } from "yargs"; | ||
|
||
class LicensePlugin implements Plugin { | ||
public readonly id = "license"; | ||
public readonly stages = [DefaultStages.check]; | ||
|
||
public defineCLIOptions(yargs: Argv<any>): Argv<any> { | ||
return yargs.options({ | ||
license: { | ||
string: true, | ||
array: true, | ||
description: `Globs matching the license files to check`, | ||
default: ["{LICENSE,README}{,.md}"], | ||
}, | ||
}); | ||
} | ||
|
||
async executeStage(context: Context, stage: Stage): Promise<void> { | ||
if (stage.id === "check") { | ||
const globs = context.argv.license as string[]; | ||
const files: string[] = []; | ||
for (const pattern of globs) { | ||
files.push( | ||
...(await glob(pattern, { | ||
cwd: context.cwd, | ||
dot: true, | ||
})), | ||
); | ||
} | ||
|
||
for (const file of files) { | ||
const filePath = path.join(context.cwd, file); | ||
if (!(await fs.pathExists(filePath))) continue; | ||
|
||
const fileContent = await fs.readFile(filePath, "utf8"); | ||
const regex = | ||
/copyright\s*(\(c\))?\s*(?<range>(?:\d{4}\s*-\s*)?(?<current>\d{4}))/gi; | ||
let match: RegExpExecArray | null; | ||
let latest: RegExpExecArray | undefined; | ||
while ((match = regex.exec(fileContent))) { | ||
if ( | ||
!latest || | ||
parseInt(match.groups!.current) > parseInt(latest.groups!.current) | ||
) { | ||
latest = match; | ||
} | ||
} | ||
|
||
if (!latest) continue; | ||
const latestYear = parseInt(latest.groups!.current); | ||
if (latestYear < new Date().getFullYear()) { | ||
context.cli.error( | ||
`File "${file}" contains an outdated copyright year: ${ | ||
latest.groups!.range | ||
}`, | ||
); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
export default LicensePlugin; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// tsconfig for building - only applies to the src directory | ||
{ | ||
"extends": "./tsconfig.json", | ||
"compilerOptions": { | ||
"rootDir": "src", | ||
"outDir": "build" | ||
}, | ||
"references": [ | ||
// Add references to other projects here | ||
{ | ||
"path": "../core/tsconfig.build.json" | ||
}, | ||
], | ||
"include": [ | ||
"src/**/*.ts" | ||
], | ||
"exclude": [ | ||
"src/**/*.test.ts" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// tsconfig for IntelliSense - active in all files in the current package | ||
{ | ||
"extends": "../../tsconfig.json", | ||
"compilerOptions": {}, | ||
"references": [ | ||
// Add references to other projects here | ||
{ | ||
"path": "../core/tsconfig.build.json" | ||
}, | ||
{ | ||
"path": "../testing/tsconfig.build.json" | ||
}, | ||
], | ||
"include": [ | ||
"src/**/*.ts" | ||
], | ||
"exclude": [ | ||
"build/**", | ||
"node_modules/**" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.