Skip to content

Commit

Permalink
feat(tooling-general): add pre-commit hook to automatically add missi…
Browse files Browse the repository at this point in the history
…ng license headers (#416)

* feat: add pre-commit hook to automatically add missing license headers

* refactor: improve code

* refactor(general): Update lockfile

---------

Co-authored-by: marc2332 <[email protected]>
Co-authored-by: cpl121 <[email protected]>
  • Loading branch information
3 people authored May 28, 2024
1 parent 21c583f commit caa0430
Show file tree
Hide file tree
Showing 8 changed files with 2,787 additions and 2,013 deletions.
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pnpm exec lint-staged --allow-empty
3 changes: 3 additions & 0 deletions .lintstagedrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"{sdk,apps}/**/*.{ts,js,mjs,tsx}": "eslint -c ./linting/.eslintrc.precommit.js --fix"
}
9 changes: 9 additions & 0 deletions linting/.eslintrc.precommit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

module.exports = {
plugins: ['license-check'],
rules: {
'license-check/license-check': 'error',
},
};
5 changes: 5 additions & 0 deletions linting/license-check/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "eslint-plugin-license-check",
"version": "1.0.0",
"main": "plugin.js"
}
10 changes: 10 additions & 0 deletions linting/license-check/plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

const licenseCheck = require('./rules/license-check.rule');

module.exports = {
rules: {
'license-check': licenseCheck,
},
};
70 changes: 70 additions & 0 deletions linting/license-check/rules/license-check.rule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

const IOTA_COPYRIGHT_HEADER = 'Copyright (c) 2024 IOTA Stiftung';
const OLD_COPYRIGHT_HEADER = 'Copyright (c) Mysten Labs, Inc.';
const MODIFICATION_COPYRIGHT_HEADER = 'Modifications Copyright (c) 2024 IOTA Stiftung';
const LICENSE_IDENTIFIER = 'SPDX-License-Identifier: Apache-2.0';

const MISSING_HEADER_MESSAGE = 'Missing or incorrect license header.';
const MISSING_MODIFICATION_MESSAGE = 'Add modification notice to the license header.';

const IOTA_LICENSE_HEADER = `// ${IOTA_COPYRIGHT_HEADER}\n// ${LICENSE_IDENTIFIER}\n\n`;
const MODIFICATION_HEADER = `\n\n// ${MODIFICATION_COPYRIGHT_HEADER}\n// ${LICENSE_IDENTIFIER}\n\n`;

function checkHeader(node, context) {
const sourceCode = context.getSourceCode();
const comments = sourceCode.getAllComments();
const firstComment = comments?.[0]?.value;

const hasIotaCopyrightHeader = firstComment?.includes(IOTA_COPYRIGHT_HEADER);
const hasOldCopyrightHeader = firstComment?.includes(OLD_COPYRIGHT_HEADER);
const hasLicenseIdentifier = comments?.[1]?.value.includes(LICENSE_IDENTIFIER);

// Check if the file has any license header.
if (
(!hasIotaCopyrightHeader && !hasOldCopyrightHeader) ||
!firstComment ||
!hasLicenseIdentifier
) {
context.report({
node,
message: MISSING_HEADER_MESSAGE,
fix(fixer) {
return fixer.insertTextBeforeRange([0, 0], IOTA_LICENSE_HEADER);
},
});

// Check if the file has the old copyright notice and has the modification header.
} else if (firstComment.includes(OLD_COPYRIGHT_HEADER)) {
const hasModificationNotice = comments[2]?.value?.includes(MODIFICATION_COPYRIGHT_HEADER);
if (!hasModificationNotice) {
context.report({
node: comments[1],
message: MISSING_MODIFICATION_MESSAGE,
fix(fixer) {
return fixer.insertTextAfter(comments[1], MODIFICATION_HEADER);
},
});
}
}
}

module.exports = {
meta: {
type: 'suggestion',
docs: {
description: 'Check and fix license header',
category: 'Stylistic Issues',
},
fixable: 'code',
schema: [],
},
create(context) {
return {
Program(node) {
checkHeader(node, context);
},
};
},
};
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"eslint:check": "eslint --max-warnings=0 .",
"eslint:fix": "pnpm run eslint:check --fix",
"lint": "pnpm run eslint:check && pnpm run prettier:check",
"lint:fix": "pnpm run eslint:fix && pnpm run prettier:fix"
"lint:fix": "pnpm run eslint:fix && pnpm run prettier:fix",
"prepare": "husky"
},
"pnpm": {
"overrides": {
Expand Down Expand Up @@ -54,13 +55,16 @@
"eslint-config-next": "14.2.3",
"eslint-config-prettier": "^8.8.0",
"eslint-import-resolver-typescript": "^3.5.5",
"eslint-plugin-license-check": "link:linting/license-check",
"eslint-plugin-header": "^3.1.1",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-require-extensions": "^0.1.3",
"eslint-plugin-tsdoc": "^0.2.17",
"eslint-plugin-unused-imports": "^3.0.0",
"graphql-config": "^5.0.3",
"husky": "^9.0.11",
"lint-staged": "^15.2.5",
"prettier": "^3.0.0",
"prettier-plugin-tailwindcss": "^0.4.1",
"tsx": "^3.12.7",
Expand Down
Loading

0 comments on commit caa0430

Please sign in to comment.