blob: 5c6a854db6d8cdc254c1c91f7bc40adce40b0cb2 [file] [log] [blame] [edit]
/* This file is a part of @mdn/browser-compat-data
* See LICENSE file for more information. */
export interface FeatureChange {
mergeCommit?: string;
number: number;
url: string;
feature: string;
}
export interface Changes {
added: FeatureChange[];
removed: FeatureChange[];
}
import chalk from 'chalk-template';
import cliProgress from 'cli-progress';
import diffFeatures from '../diff-features.js';
import { queryPRs } from './utils.js';
/**
* Format a feature change in Markdown
* @param obj The feature change to format
* @returns The formatted feature change
*/
const featureBullet = (obj: FeatureChange) =>
`- \`${obj.feature}\` ([#${obj.number}](${obj.url}))`;
/**
* Format all the feature changes in Markdown
* @param changes The changes to format
* @returns The formatted changes
*/
export const formatChanges = (changes: Changes): string => {
const output: string[] = [];
if (changes.removed.length) {
output.push('### Removals', '');
for (const removal of changes.removed) {
output.push(featureBullet(removal));
}
output.push('');
}
if (changes.added.length) {
output.push('### Additions', '');
for (const addition of changes.added) {
output.push(featureBullet(addition));
}
output.push('');
}
return output.join('\n');
};
/**
* Get all the pulls that have been merged on GitHub
* @param fromDate The start date to get merged pulls from
* @returns The pull requests that have been merged
*/
const pullsFromGitHub = (fromDate: string): FeatureChange[] =>
queryPRs({
search: `is:pr merged:>=${fromDate}`,
json: 'number,url,mergeCommit',
jq: '[.[] | { mergeCommit: .mergeCommit.oid, number: .number, url: .url }]', // Flatten the structure provided by GitHub
});
/**
* Get the diff from the pull request
* @param pull The pull request to test
* @returns The changes from the pull request
*/
const getDiff = async (
pull: FeatureChange,
): Promise<{ added: string[]; removed: string[] }> => {
let diff;
try {
diff = await diffFeatures({ ref1: pull.mergeCommit, quiet: true });
} catch (e) {
throw new Error(
chalk`{red ${e}}\n {yellow (Failed to diff features for #${pull.number}, skipping)}`,
);
}
if (diff.added.length && diff.removed.length) {
console.log(
chalk` | #${pull.number} - {blue ({green ${diff.added.length} added}, {red ${diff.removed.length} removed})}`,
);
} else if (diff.added.length) {
console.log(
chalk` | #${pull.number} - {blue ({green ${diff.added.length} added})}`,
);
} else if (diff.removed.length) {
console.log(
chalk` | #${pull.number} - {blue ({red ${diff.removed.length} removed})}`,
);
} else {
console.log(chalk` | #${pull.number} - {blue (No feature count changes)}`);
}
return diff;
};
/**
* Get changes from the pull requests that have been merged since a specified date
* @param date The starting date to query pull requests from
* @returns The changes from all of the pull requests
*/
export const getChanges = async (date: string): Promise<Changes> => {
const progressBar = new cliProgress.SingleBar(
{},
cliProgress.Presets.shades_classic,
);
const pulls = pullsFromGitHub(date);
const changes: Changes = {
added: [],
removed: [],
};
progressBar.start(pulls.length, 0);
await Promise.all(
pulls.map(async (pull) => {
const diff = await getDiff(pull);
changes.added.push(
...diff.added.map((feature) => ({
number: pull.number,
url: pull.url,
feature,
})),
);
changes.removed.push(
...diff.removed.map((feature) => ({
number: pull.number,
url: pull.url,
feature,
})),
);
progressBar.increment();
}),
);
progressBar.stop();
console.log('\n');
changes.added.sort((a, b) => a.feature.localeCompare(b.feature));
changes.removed.sort((a, b) => a.feature.localeCompare(b.feature));
return changes;
};