Skip to content

Commit

Permalink
[devx] Create script to stage files by CODEOWNER (elastic#203940)
Browse files Browse the repository at this point in the history
  • Loading branch information
clintandrewhall authored Dec 17, 2024
1 parent 3d8ac49 commit 714ba67
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 0 deletions.
11 changes: 11 additions & 0 deletions scripts/stage_by_owner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* 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".
*/

require('../src/setup_node_env');
require('../src/dev/stage_by_owner');
96 changes: 96 additions & 0 deletions src/dev/stage_by_owner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* 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 simpleGit from 'simple-git';

import { run } from '@kbn/dev-cli-runner';
import { getOwningTeamsForPath, getCodeOwnersEntries, CodeOwnersEntry } from '@kbn/code-owners';
import { asyncForEach } from '@kbn/std';
import { inspect } from 'util';

const git = simpleGit();

interface File {
path: string;
staged: boolean;
}

// Function to get the list of changed files
const getChangedFiles = async (): Promise<File[]> => {
const { staged, files } = await git.status();
return files.map((file) => ({ path: file.path, staged: staged.includes(file.path) }));
};

run(
async ({ flags, log }) => {
const {
_: [owner],
} = flags;

const changedFiles = await getChangedFiles();
const owners: { staged: Record<string, string[]>; unstaged: Record<string, string[]> } = {
staged: {},
unstaged: {},
};

let codeOwnersEntries: CodeOwnersEntry[] = [];

try {
codeOwnersEntries = getCodeOwnersEntries();
} catch (e) {
log.error('CODEOWNERS cannot be read.');
process.exit(1);
}

const getOwners = (file: string) => {
const teams = getOwningTeamsForPath(file, codeOwnersEntries);

if (teams.length === 0) {
log.warning(`No owner found for ${file}`);
return [];
}

return teams;
};

for (const file of changedFiles) {
const fileOwners = getOwners(file.path);

if (fileOwners) {
await asyncForEach(fileOwners, async (fileOwner) => {
const loc = file.staged ? 'staged' : 'unstaged';

owners[loc][fileOwner] = [
...(owners[loc][fileOwner] || []),
file.path + (fileOwners.length > 1 ? ` (+${fileOwners.length - 1})` : ''),
];

if (owner && fileOwner === owner) {
await git.add(file.path);
log.info(`Staged ${file.path}`);
}
});
}
}

if (!owner) {
log.info(inspect(owners, { colors: true, depth: null }));
}

log.info('Done.');
},
{
usage: 'node src/dev/stage_by_owner.ts [owner]',
description: `
This script stages files based on the CODEOWNERS file.
If an owner is provided, it stages the files owned by that owner.
Otherwise, it outputs changed files, grouped by owner.
`,
}
);
1 change: 1 addition & 0 deletions src/dev/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,6 @@
"@kbn/core-test-helpers-kbn-server",
"@kbn/dev-proc-runner",
"@kbn/core-i18n-server-internal",
"@kbn/code-owners",
]
}

0 comments on commit 714ba67

Please sign in to comment.