mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 10:40:07 -04:00
Currently we remove CODEOWNERS on backport branches to avoid review assignments: reviews were already collected on the source pull request. If there's a conflict, it will go through another round of review but not require all the original assignees. We want to re-add the file for our own tooling, and to avoid CODEOWNERS merge conflicts on backports. To do this, we're going to add a global override to code assignments on backport branches. This updates our CODEOWNERS libraries to ignore assignments to `kibanamachine`. --------- Co-authored-by: Dzmitry Lemechko <dzmitry.lemechko@elastic.co>
103 lines
3.9 KiB
TypeScript
103 lines
3.9 KiB
TypeScript
/*
|
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
* or more contributor license agreements. Licensed under the "Elastic License
|
|
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
|
* Public License v 1"; you may not use this file except in compliance with, at
|
|
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
|
* License v3.0 only", or the "Server Side Public License, v 1".
|
|
*/
|
|
|
|
import { REPO_ROOT } from '@kbn/repo-info';
|
|
import { createFailError, createFlagError } from '@kbn/dev-cli-errors';
|
|
import { join as joinPath } from 'path';
|
|
import { existsSync, readFileSync } from 'fs';
|
|
import { run } from '@kbn/dev-cli-runner';
|
|
|
|
import type { Ignore } from 'ignore';
|
|
import ignore from 'ignore';
|
|
|
|
export interface PathWithOwners {
|
|
path: string;
|
|
teams: string;
|
|
ignorePattern: Ignore;
|
|
}
|
|
const existOrThrow = (targetFile: string) => {
|
|
if (existsSync(targetFile) === false)
|
|
throw createFailError(`Unable to determine code owners: file ${targetFile} Not Found`);
|
|
};
|
|
|
|
/**
|
|
* Get the .github/CODEOWNERS entries, prepared for path matching.
|
|
* The last matching CODEOWNERS entry has highest precedence:
|
|
* https://help.github.com/articles/about-codeowners/
|
|
* so entries are returned in reversed order to later search for the first match.
|
|
*/
|
|
export function getPathsWithOwnersReversed(): PathWithOwners[] {
|
|
const codeownersPath = joinPath(REPO_ROOT, '.github', 'CODEOWNERS');
|
|
existOrThrow(codeownersPath);
|
|
const codeownersContent = readFileSync(codeownersPath, { encoding: 'utf8', flag: 'r' });
|
|
const codeownersLines = codeownersContent.split(/\r?\n/);
|
|
const codeowners = codeownersLines
|
|
.map((line) => line.trim())
|
|
.filter((line) => line && line[0] !== '#')
|
|
// kibanamachine is an assignment override on backport branches to avoid review requests
|
|
.filter((line) => line && !line.includes('@kibanamachine'));
|
|
|
|
const pathsWithOwners: PathWithOwners[] = codeowners.map((c) => {
|
|
const [path, ...ghTeams] = c.split(/\s+/);
|
|
const cleanedPath = path.replace(/\/$/, ''); // remove trailing slash
|
|
return {
|
|
path: cleanedPath,
|
|
teams: ghTeams.map((t) => t.replace('@', '')).join(),
|
|
// register CODEOWNERS entries with the `ignores` lib for later path matching
|
|
ignorePattern: ignore().add([cleanedPath]),
|
|
};
|
|
});
|
|
|
|
return pathsWithOwners.reverse();
|
|
}
|
|
|
|
/**
|
|
* Get the GitHub CODEOWNERS for a file in the repository
|
|
* @param filePath the file to get code owners for
|
|
* @param reversedCodeowners a cached reversed code owners list, use to speed up multiple requests
|
|
*/
|
|
export function getCodeOwnersForFile(
|
|
filePath: string,
|
|
reversedCodeowners?: PathWithOwners[]
|
|
): string | undefined {
|
|
const pathsWithOwners = reversedCodeowners ?? getPathsWithOwnersReversed();
|
|
|
|
const match = pathsWithOwners.find((p) => p.ignorePattern.test(filePath).ignored);
|
|
|
|
return match?.teams;
|
|
}
|
|
|
|
/**
|
|
* Run the getCodeOwnersForFile() method above.
|
|
* Report back to the cli with either success and the owner(s), or a failure.
|
|
*
|
|
* This function depends on a --file param being passed on the cli, like this:
|
|
* $ node scripts/get_owners_for_file.js --file SOME-FILE
|
|
*/
|
|
export async function runGetOwnersForFileCli() {
|
|
run(
|
|
async ({ flags, log }) => {
|
|
const targetFile = flags.file as string;
|
|
if (!targetFile) throw createFlagError(`Missing --file argument`);
|
|
existOrThrow(targetFile); // This call is duplicated in getPathsWithOwnersReversed(), so this is a short circuit
|
|
const result = getCodeOwnersForFile(targetFile);
|
|
if (result) log.success(result);
|
|
else log.error(`Ownership of file [${targetFile}] is UNKNOWN`);
|
|
},
|
|
{
|
|
description: 'Report file ownership from GitHub CODEOWNERS file.',
|
|
flags: {
|
|
string: ['file'],
|
|
help: `
|
|
--file Required, path to the file to report owners for.
|
|
`,
|
|
},
|
|
}
|
|
);
|
|
}
|