Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gas-reporter): allow gas-reporter to parse stdin #1688

Merged
merged 4 commits into from
Oct 3, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 34 additions & 12 deletions packages/gas-report/ts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type Options = {
path: string[];
save?: string;
compare?: string;
stdin?: boolean;
};

type GasReportEntry = {
Expand All @@ -52,20 +53,22 @@ const commandModule: CommandModule<Options, Options> = {
return yargs.options({
save: { type: "string", desc: "Save the gas report to a file" },
compare: { type: "string", desc: "Compare to an existing gas report" },
stdin: { type: "boolean", desc: "Parse the gas report from stdin instead of running an internal test command" },
alvrs marked this conversation as resolved.
Show resolved Hide resolved
});
},

async handler({ save, compare }) {
async handler(options) {
let gasReport: GasReport;
try {
gasReport = await runGasReport();
gasReport = await runGasReport(options);
} catch (error) {
console.error(error);
setTimeout(() => process.exit());
return;
}

// If this gas report should be compared to an existing one, load the existing one
let { compare } = options;
if (compare) {
try {
const compareGasReport: GasReport = JSON.parse(readFileSync(compare, "utf8"));
Expand All @@ -84,35 +87,40 @@ const commandModule: CommandModule<Options, Options> = {
printGasReport(gasReport, compare);

// Save gas report to file if requested
if (save) saveGasReport(gasReport, save);
if (options.save) saveGasReport(gasReport, options.save);

process.exit(0);
},
};

export default commandModule;

async function runGasReport(): Promise<GasReport> {
async function runGasReport(options: Options): Promise<GasReport> {
console.log("Running gas report");
const gasReport: GasReport = [];

// Extract the logs from the child process
let stdout: string;
let logs: string;
try {
// Run the generated file using forge
const child = execa("forge", ["test", "-vvv"], {
stdio: ["inherit", "pipe", "inherit"],
env: { GAS_REPORTER_ENABLED: "true" },
});
stdout = (await child).stdout;
if (options.stdin) {
// Read the logs from stdin
logs = await readStdIn();
} else {
// Run the default test command to capture the logs
const child = execa("forge", ["test", "-vvv"], {
stdio: ["inherit", "pipe", "inherit"],
env: { GAS_REPORTER_ENABLED: "true" },
});
logs = (await child).stdout;
}
} catch (error: any) {
console.log(error.stdout ?? error);
console.log(chalk.red("\n-----------\nError while running the gas report (see above)"));
throw error;
}

// Extract the gas reports from the logs
const lines = stdout.split("\n").map(stripAnsi);
const lines = logs.split("\n").map(stripAnsi);
const gasReportPattern = /^\s*GAS REPORT: (\d+) (.*)$/;
const testFunctionPattern = /^\[(?:PASS|FAIL).*\] (\w+)\(\)/;
const testFilePattern = /^Running \d+ tests? for (.*):(.*)$/;
Expand Down Expand Up @@ -191,3 +199,17 @@ function saveGasReport(gasReport: GasReport, path: string) {
console.log(chalk.bold(`Saving gas report to ${path}`));
writeFileSync(path, `${JSON.stringify(gasReport, null, 2)}\n`);
}

function readStdIn(): Promise<string> {
return new Promise((resolve) => {
let data = "";

process.stdin.on("data", (chunk) => {
data += chunk;
});

process.stdin.on("end", () => {
resolve(data);
});
});
}