Skip to content

Commit

Permalink
perf(scripts/diff-features): fetch enumerations async
Browse files Browse the repository at this point in the history
  • Loading branch information
caugner committed Nov 6, 2024
1 parent 65becf4 commit c8bf6ce
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 69 deletions.
82 changes: 37 additions & 45 deletions scripts/diff-features.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
/* This file is a part of @mdn/browser-compat-data
* See LICENSE file for more information. */

import { execSync } from 'node:child_process';
import { exec, execSync } from 'node:child_process';
import fs from 'node:fs';
import { promisify } from 'node:util';
import path from 'node:path';

import esMain from 'es-main';
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import { temporaryDirectoryTask } from 'tempy';

/**
* Executes a command asynchronously.
* @param command The command to execute asynchronously.
* @returns The output of the command.
*/
const execAsync = async (command: string): Promise<string> => {
const result = await promisify(exec)(command, { encoding: 'utf-8' });

return result.stdout.trim();
};

/**
* Compare two references and print diff as Markdown or JSON
Expand All @@ -16,14 +30,14 @@ import { hideBin } from 'yargs/helpers';
* @param opts.format Format to export data as (either 'markdown' or 'json', default 'json')
* @param opts.github Whether to obtain artifacts from GitHub
*/
const main = (opts: {
const main = async (opts: {
ref1: string | undefined;
ref2: string | undefined;
format?: string;
github?: boolean;
}): void => {
}): Promise<void> => {
const { ref1, ref2, format, github } = opts;
const results = diff({ ref1, ref2, github });
const results = await diff({ ref1, ref2, github });

if (format === 'markdown') {
printMarkdown(results.added, results.removed);
Expand All @@ -41,12 +55,12 @@ const main = (opts: {
* @param opts.quiet If true, don't log to console
* @returns Diff between two refs
*/
const diff = (opts: {
const diff = async (opts: {
ref1?: string;
ref2?: string;
github?: boolean;
quiet?: boolean;
}): { added: string[]; removed: string[] } => {
}): Promise<{ added: string[]; removed: string[] }> => {
const { ref1, ref2, github, quiet } = opts;
let refA, refB;

Expand All @@ -64,8 +78,8 @@ const diff = (opts: {
refB = `${ref1}`;
}

const aSide = enumerate(refA, github === false, quiet);
const bSide = enumerate(refB, github === false, quiet);
const aSide = await enumerate(refA, github === false, quiet);
const bSide = await enumerate(refB, github === false, quiet);

return {
added: [...bSide].filter((feature) => !aSide.has(feature)),
Expand All @@ -80,14 +94,14 @@ const diff = (opts: {
* @param quiet If true, don't log to console
* @returns Feature list from reference
*/
const enumerate = (
const enumerate = async (
ref: string,
skipGithub: boolean,
quiet = false,
): Set<string> => {
): Promise<Set<string>> => {
if (!skipGithub) {
try {
return new Set(getEnumerationFromGithub(ref));
return new Set(await getEnumerationFromGithub(ref));
} catch (e) {
if (!quiet) {
console.error(
Expand All @@ -105,50 +119,28 @@ const enumerate = (
* @param ref Reference to obtain features for
* @returns Feature list from reference
*/
const getEnumerationFromGithub = (ref: string): string[] => {
const getEnumerationFromGithub = async (ref: string): Promise<string[]> => {
const ENUMERATE_WORKFLOW = '15595228';
const ENUMERATE_WORKFLOW_ARTIFACT = 'enumerate-features';
const ENUMERATE_WORKFLOW_FILE = 'features.json';

/**
* Unlinks the workflow file
*/
const unlinkFile = () => {
try {
fs.unlinkSync(ENUMERATE_WORKFLOW_FILE);
} catch (err: any) {
if (err.code == 'ENOENT') {
return;
}
throw err;
}
};

const hash = execSync(`git rev-parse ${ref}`, {
encoding: 'utf-8',
}).trim();
const workflowRun = execSync(
const hash = await execAsync(`git rev-parse ${ref}`);
const workflowRun = await execAsync(
`gh api /repos/:owner/:repo/actions/workflows/${ENUMERATE_WORKFLOW}/runs\\?branch=main\\&head_sha=${hash}\\&per_page=1 --jq '[.workflow_runs[] | select(.head_sha=="${hash}") | .id] | first'`,
{
encoding: 'utf-8',
},
).trim();
);

if (!workflowRun) {
throw Error('No workflow run found for commit.');
}

try {
unlinkFile();
execSync(
`gh run download ${workflowRun} -n ${ENUMERATE_WORKFLOW_ARTIFACT}`,
);
return JSON.parse(
fs.readFileSync(ENUMERATE_WORKFLOW_FILE, { encoding: 'utf-8' }),
return await temporaryDirectoryTask(async (tempdir) => {
await execAsync(
`gh run download ${workflowRun} -n ${ENUMERATE_WORKFLOW_ARTIFACT} --dir ${tempdir}`,
);
} finally {
unlinkFile();
}
const file = path.join(tempdir, ENUMERATE_WORKFLOW_FILE);

return JSON.parse(fs.readFileSync(file, { encoding: 'utf-8' }));
});
};

/**
Expand Down Expand Up @@ -249,7 +241,7 @@ if (esMain(import.meta)) {
},
);

main(argv as any);
await main(argv as any);
}

export default diff;
50 changes: 26 additions & 24 deletions scripts/release/changes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@ const pullsFromGitHub = (fromDate: string): FeatureChange[] =>
* @param pull The pull request to test
* @returns The changes from the pull request
*/
const getDiff = (
const getDiff = async (
pull: FeatureChange,
): { added: string[]; removed: string[] } => {
): Promise<{ added: string[]; removed: string[] }> => {
let diff;

try {
diff = diffFeatures({ ref1: pull.mergeCommit, quiet: true });
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)}`,
Expand Down Expand Up @@ -123,27 +123,29 @@ export const getChanges = async (date: string): Promise<Changes> => {

progressBar.start(pulls.length, 0);

for (const pull of pulls) {
const diff = 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();
}
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');
Expand Down

0 comments on commit c8bf6ce

Please sign in to comment.