mirror of
https://github.com/grafana/grafana.git
synced 2024-11-28 11:44:26 -06:00
43828e829b
* wip * finish script * limit by message * fix filter message * Add template * improve template * codeowners devdep
149 lines
4.0 KiB
TypeScript
149 lines
4.0 KiB
TypeScript
import { betterer, BettererFileIssues } from '@betterer/betterer';
|
|
import Codeowners from 'codeowners';
|
|
import { readFile, writeFile } from 'fs/promises';
|
|
import { template } from 'lodash';
|
|
import path from 'path';
|
|
import { hideBin } from 'yargs/helpers';
|
|
import yargs from 'yargs/yargs';
|
|
|
|
const argv = yargs(hideBin(process.argv))
|
|
.option('template', {
|
|
demandOption: true,
|
|
alias: 't',
|
|
describe: 'Path to a template to use for each issue. See source bettererIssueTemplate.md for an example',
|
|
type: 'string',
|
|
default: './scripts/cli/bettererIssueTemplate.md',
|
|
})
|
|
.option('output', {
|
|
demandOption: true,
|
|
alias: 'o',
|
|
describe: 'Path to directory to save issues to',
|
|
type: 'string',
|
|
})
|
|
.option('test', {
|
|
demandOption: true,
|
|
alias: 'b',
|
|
describe: 'Name of the betterer test to produce the report for',
|
|
type: 'string',
|
|
})
|
|
.option('test-message', {
|
|
alias: 'm',
|
|
describe: 'Filter issues containing this message',
|
|
type: 'string',
|
|
})
|
|
.option('single-owner', {
|
|
type: 'boolean',
|
|
alias: 's',
|
|
describe: 'Only use first owner for files with multiple owners',
|
|
default: false,
|
|
})
|
|
|
|
.usage('Usage: yarn betterer:issues -t [path] -o [path] -b [string]')
|
|
.version(false)
|
|
.help('help').argv;
|
|
|
|
interface FileDetails {
|
|
fileName: string;
|
|
issueCount: number;
|
|
issues: BettererFileIssues;
|
|
}
|
|
|
|
// really dumb and simple pluralize function. not meant to be exhaustive
|
|
function plural(word: string, count: number) {
|
|
if (count === 0 || count > 1) {
|
|
return word + 's';
|
|
}
|
|
|
|
return word;
|
|
}
|
|
|
|
async function main() {
|
|
const args = await argv;
|
|
const templatePath = path.resolve(args.template);
|
|
const outputPath = path.resolve(args.output);
|
|
const templateString = (await readFile(templatePath)).toString();
|
|
|
|
const owners = new Codeowners();
|
|
const results = await betterer.results();
|
|
|
|
const filesByOwner: Record<string, FileDetails[]> = {};
|
|
|
|
for (const testResults of results.resultSummaries) {
|
|
if (testResults.name !== args.test) {
|
|
continue;
|
|
}
|
|
|
|
if (typeof testResults.details === 'string') {
|
|
continue;
|
|
}
|
|
|
|
for (const _fileName in testResults.details) {
|
|
const fileName = _fileName.replace(process.cwd() + '/', '');
|
|
const _details = testResults.details[_fileName];
|
|
let ownersForFile = owners.getOwner(fileName);
|
|
|
|
if (args.singleOwner) {
|
|
ownersForFile = [ownersForFile[0]];
|
|
}
|
|
|
|
const filterByMessage = args.testMessage?.length ? args.testMessage.toLowerCase() : undefined;
|
|
|
|
const filteredDetails = filterByMessage
|
|
? _details.filter((v) => v.message.toLowerCase().includes(filterByMessage))
|
|
: _details;
|
|
|
|
const numberOfIssues = filteredDetails.length;
|
|
|
|
if (numberOfIssues === 0) {
|
|
continue;
|
|
}
|
|
|
|
for (const owner of ownersForFile) {
|
|
if (!filesByOwner[owner]) {
|
|
filesByOwner[owner] = [];
|
|
}
|
|
|
|
filesByOwner[owner].push({
|
|
fileName,
|
|
issueCount: numberOfIssues,
|
|
issues: filteredDetails,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
const contexts = Object.entries(filesByOwner).map(([owner, files]) => {
|
|
const fileCount = files.length;
|
|
const totalIssueCount = files.reduce((acc, v) => acc + v.issueCount, 0);
|
|
|
|
return {
|
|
owner,
|
|
files,
|
|
fileCount,
|
|
totalIssueCount,
|
|
issueFilter: args.test,
|
|
issueMessageFilter: args.testMessage,
|
|
};
|
|
});
|
|
|
|
const compiledTemplate = template(templateString, { imports: { plural } });
|
|
|
|
for (const context of contexts) {
|
|
const fileSafeOwner = context.owner.replace(/[^a-z0-9-]/gi, '_');
|
|
const fileSafeTestName = args.test.replace(/[^a-z0-9-]/gi, '_');
|
|
const outputFilePath = path.join(outputPath, `${fileSafeTestName}_${fileSafeOwner}.txt`);
|
|
const printed = compiledTemplate(context);
|
|
await writeFile(outputFilePath, printed);
|
|
|
|
const indented = printed
|
|
.split('\n')
|
|
.map((v) => `\t${v}`)
|
|
.join('\n');
|
|
|
|
console.log(`Printed issue for owner`, context.owner, 'to', outputFilePath);
|
|
console.log(indented);
|
|
}
|
|
}
|
|
|
|
main().catch(console.error);
|