scripts: add script to print code ownership
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -92,6 +92,7 @@
|
||||
"prettier": "^2.2.1",
|
||||
"semver": "^7.5.3",
|
||||
"shx": "^0.3.2",
|
||||
"sloc": "^0.3.1",
|
||||
"ts-node": "^10.4.0",
|
||||
"typescript": "~5.1.0"
|
||||
},
|
||||
|
||||
Executable
+139
@@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env node
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const fs = require('fs-extra');
|
||||
const globby = require('globby');
|
||||
const sloc = require('sloc');
|
||||
const codeownersUtils = require('codeowners-utils');
|
||||
const { resolve: resolvePath } = require('path');
|
||||
|
||||
async function loadOwners(rootDir) {
|
||||
const codeowners = await codeownersUtils.loadOwners(rootDir);
|
||||
|
||||
return function getOwners(path) {
|
||||
const { owners } = codeownersUtils.matchFile(path, codeowners);
|
||||
if (
|
||||
owners.includes('@backstage/maintainers') &&
|
||||
owners.includes('@backstage/reviewers')
|
||||
) {
|
||||
return owners.filter(owner => owner !== '@backstage/reviewers');
|
||||
}
|
||||
return owners;
|
||||
};
|
||||
}
|
||||
|
||||
function createLocCounter(rootDir) {
|
||||
return async path => {
|
||||
const content = await fs.readFile(resolvePath(rootDir, path), 'utf-8');
|
||||
const stats = sloc(content, 'ts');
|
||||
return stats.source;
|
||||
};
|
||||
}
|
||||
|
||||
async function printOwnerDirectories(allFiles, getOwners, getLoc, onlyOwner) {
|
||||
const countByPath = new Map();
|
||||
|
||||
let total = 0;
|
||||
let totalShare = 0;
|
||||
for (const file of allFiles) {
|
||||
const owners = getOwners(file);
|
||||
const loc = await getLoc(file);
|
||||
|
||||
if (owners.includes(onlyOwner)) {
|
||||
const share = loc / owners.length;
|
||||
total += loc;
|
||||
totalShare += share;
|
||||
|
||||
const path = file.split('/').slice(0, 2).join('/');
|
||||
if ((await fs.stat(path)).isDirectory()) {
|
||||
countByPath.set(path, (countByPath.get(path) || 0) + share);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const sortedPaths = Array.from(countByPath)
|
||||
.map(([path, loc]) => ({ path, loc: Math.round(loc) }))
|
||||
.sort((a, b) => b.loc - a.loc);
|
||||
|
||||
const maxPathLen = Math.max(...sortedPaths.map(({ path }) => path.length));
|
||||
for (const { path, loc } of sortedPaths) {
|
||||
console.log(`${path.padEnd(maxPathLen)} ${loc}`);
|
||||
}
|
||||
console.log();
|
||||
console.log('Total share:', Math.round(totalShare));
|
||||
console.log('Total lines of code:', total);
|
||||
}
|
||||
|
||||
async function printAllOwners(allFiles, getOwners, getLoc) {
|
||||
const countByOwners = new Map();
|
||||
|
||||
let total = 0;
|
||||
for (const file of allFiles) {
|
||||
const owners = getOwners(file);
|
||||
const loc = await getLoc(file);
|
||||
|
||||
total += loc;
|
||||
const share = loc / owners.length;
|
||||
for (const owner of owners) {
|
||||
countByOwners.set(owner, (countByOwners.get(owner) || 0) + share);
|
||||
}
|
||||
}
|
||||
|
||||
const sortedOwners = Array.from(countByOwners)
|
||||
.map(([owner, loc]) => ({ owner, loc: Math.round(loc) }))
|
||||
.sort((a, b) => b.loc - a.loc);
|
||||
|
||||
const maxOwnerLen = Math.max(
|
||||
...sortedOwners.map(({ owner }) => owner.length),
|
||||
);
|
||||
for (const { owner, loc } of sortedOwners) {
|
||||
console.log(`${owner.padEnd(maxOwnerLen)} ${loc}`);
|
||||
}
|
||||
console.log();
|
||||
console.log('Total lines of code:', total);
|
||||
}
|
||||
|
||||
async function main(onlyOwner) {
|
||||
const rootDir = resolvePath(__dirname, '..');
|
||||
|
||||
const allFiles = await globby(
|
||||
[
|
||||
'**/*.{js,jsx,ts,tsx,mjs,cjs}',
|
||||
'!**/*.{generated,test}.*',
|
||||
'!**/{__fixtures__,fixtures}',
|
||||
],
|
||||
{
|
||||
cwd: rootDir,
|
||||
gitignore: true,
|
||||
followSymbolicLinks: false,
|
||||
},
|
||||
);
|
||||
|
||||
const getOwners = await loadOwners(rootDir);
|
||||
const getLoc = createLocCounter(rootDir);
|
||||
|
||||
if (onlyOwner) {
|
||||
await printOwnerDirectories(allFiles, getOwners, getLoc, onlyOwner);
|
||||
} else {
|
||||
await printAllOwners(allFiles, getOwners, getLoc);
|
||||
}
|
||||
}
|
||||
|
||||
main(...process.argv.slice(2)).catch(err => {
|
||||
console.error(err.stack);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -22644,12 +22644,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cli-table@npm:^0.3.1":
|
||||
version: 0.3.6
|
||||
resolution: "cli-table@npm:0.3.6"
|
||||
"cli-table@npm:^0.3.1, cli-table@npm:^0.3.11":
|
||||
version: 0.3.11
|
||||
resolution: "cli-table@npm:0.3.11"
|
||||
dependencies:
|
||||
colors: 1.0.3
|
||||
checksum: b0cd08578c810240920438cc2b3ffb4b4f5106b29f3362707f1d8cfc0c0440ad2afb70b96e30ce37f72f0ffe1e844ae7341dde4df17d51ad345eb186a5903af2
|
||||
checksum: 59fb61f992ac9bc8610ed98c72bf7f5d396c5afb42926b6747b46b0f8bb98a0dfa097998e77542ac334c1eb7c18dbf4f104d5783493273c5ec4c34084aa7c663
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -39193,7 +39193,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"readdirp@npm:~3.6.0":
|
||||
"readdirp@npm:^3.3.0, readdirp@npm:~3.6.0":
|
||||
version: 3.6.0
|
||||
resolution: "readdirp@npm:3.6.0"
|
||||
dependencies:
|
||||
@@ -40117,6 +40117,7 @@ __metadata:
|
||||
prettier: ^2.2.1
|
||||
semver: ^7.5.3
|
||||
shx: ^0.3.2
|
||||
sloc: ^0.3.1
|
||||
ts-node: ^10.4.0
|
||||
typescript: ~5.1.0
|
||||
languageName: unknown
|
||||
@@ -40900,6 +40901,20 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"sloc@npm:^0.3.1":
|
||||
version: 0.3.1
|
||||
resolution: "sloc@npm:0.3.1"
|
||||
dependencies:
|
||||
async: ^3.2.4
|
||||
cli-table: ^0.3.11
|
||||
commander: ^11.0.0
|
||||
readdirp: ^3.3.0
|
||||
bin:
|
||||
sloc: bin/sloc
|
||||
checksum: 3075150912b4fbb90167c446b155fcfffa20351245d7ae2a7139b2c3ba5dd9fd01fe97fc11a917d5f6a66778c3a9ab4c6ceff0bcd234338f38942fb7238ab927
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"slugify@npm:^1.6.4":
|
||||
version: 1.6.6
|
||||
resolution: "slugify@npm:1.6.6"
|
||||
|
||||
Reference in New Issue
Block a user