Skip to content

Instantly share code, notes, and snippets.

@philipjfulcher
Created February 27, 2024 20:01
Show Gist options
  • Save philipjfulcher/965e896a1838df87ea206c1eb822f01d to your computer and use it in GitHub Desktop.
Save philipjfulcher/965e896a1838df87ea206c1eb822f01d to your computer and use it in GitHub Desktop.
Churn report example
import { createProjectGraphAsync } from '@nx/devkit';
import { execSync } from 'node:child_process';
export async function churnGenerator(
) {
const graph = await createProjectGraphAsync();
const projects: Record<string, { ancestors: number; affected: number }> = {};
console.log('Calculating ancestors');
for (const project in graph.dependencies) {
graph.dependencies[project]
.filter(
(project) =>
!project.target.startsWith('npm') &&
graph.nodes[project.target].type === 'lib'
)
.forEach((dependency) => {
if (projects[dependency.target] !== undefined) {
projects[dependency.target].ancestors++;
} else {
projects[dependency.target] = {
ancestors: 1,
affected: 0,
};
}
});
}
console.log(projects);
console.log('Calculating how often projects were affected');
const gitOutput = execSync(
'git log --pretty=format:"%H" --since=15.days'
).toString('utf-8');
const hashes = gitOutput.split('\n');
const pairedHashes = hashes.reduce<Array<[string, string] | [string]>>(
(acc, cur) => {
const lastTuple = acc.pop();
if (!lastTuple) {
acc.push([cur]);
} else if (lastTuple.length === 1) {
acc.push([...lastTuple, cur]);
} else if (lastTuple.length === 2) {
acc.push(lastTuple);
acc.push([lastTuple[1], cur]);
}
return acc;
},
[]
);
pairedHashes.forEach((pairedHash) => {
const affectedOutput = execSync(
`yarn nx show projects --affected --head=${pairedHash[0]} --base=${pairedHash[1]}`
).toString('utf-8');
const affected = affectedOutput.split('\n').slice(1, -1);
affected.forEach((project) => {
if (projects[project] !== undefined) {
projects[project].affected++;
}
});
});
const sortedProjects: { project: string; score: number }[] = [];
for (const project in projects) {
sortedProjects.push({
project,
score: projects[project].affected * projects[project].ancestors,
});
}
sortedProjects.sort((a, b) => b.score - a.score);
console.log(sortedProjects);
}
export default churnGenerator;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment