Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
22 changes: 16 additions & 6 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -230,15 +230,17 @@ jobs:
auth:
username: $DOCKERHUB_USERNAME
password: $DOCKERHUB_TOKEN
resource_class: large
steps:
- checkout
- attach_workspace:
at: .
- run: npm run test:gas
- run: npx codechecks codechecks.unit.yml
- run:
name: Upload gas reports
command: |
npx hardhat test:merge-gas-reports gasReporterOutput-*.json
npx codechecks codechecks.unit.yml
- store_artifacts:
path: test-gas-used.log
path: gasReporterOutput.json
job-unit-tests:
working_directory: ~/repo
docker:
Expand All @@ -259,11 +261,18 @@ jobs:
set +e
circleci tests glob 'test/contracts/*.js' |
circleci tests split |
xargs npm test
xargs npm test -- --gas
EXIT_CODE=$?
cat test-gas-used.log
printf "\\n"
exit $EXIT_CODE
- run:
name: Save gas report
command: |
mv gasReporterOutput.json ./gasReporterOutput-$CIRCLE_NODE_INDEX.json
- persist_to_workspace:
root: .
paths:
- gasReporterOutput-*.json
job-validate-deployments:
working_directory: ~/repo
docker:
Expand Down Expand Up @@ -324,6 +333,7 @@ workflows:
- job-unit-tests-gas-report:
requires:
- job-prepare
- job-unit-tests
- job-test-deploy-script:
requires:
- job-prepare
Expand Down
2 changes: 1 addition & 1 deletion .circleci/src/jobs/job-fork-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ steps:
command: npm run fork
background: true
- cmd-wait-for-port:
port: 8545
port: 8545
- run: npx hardhat test:integration:l1 --compile --deploy --use-fork
10 changes: 6 additions & 4 deletions .circleci/src/jobs/job-unit-tests-gas-report.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# Measures deployment and transaction gas usage in unit tests
{{> job-header.yml}}
resource_class: large
steps:
- checkout
- attach_workspace:
at: .
- run: npm run test:gas
- run: npx codechecks codechecks.unit.yml
- run:
name: Upload gas reports
command: |
npx hardhat test:merge-gas-reports gasReporterOutput-*.json
npx codechecks codechecks.unit.yml
- store_artifacts:
path: test-gas-used.log
path: gasReporterOutput.json
11 changes: 9 additions & 2 deletions .circleci/src/jobs/job-unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,15 @@ steps:
set +e
circleci tests glob 'test/contracts/*.js' |
circleci tests split |
xargs npm test
xargs npm test -- --gas
EXIT_CODE=$?
cat test-gas-used.log
printf "\\n"
exit $EXIT_CODE
- run:
name: Save gas report
command: |
mv gasReporterOutput.json ./gasReporterOutput-$CIRCLE_NODE_INDEX.json
- persist_to_workspace:
root: .
paths:
- gasReporterOutput-*.json
3 changes: 3 additions & 0 deletions .circleci/src/snippets/require-unit-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
requires:
- job-prepare
- job-unit-tests
2 changes: 1 addition & 1 deletion .circleci/src/workflows/workflow-all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- job-unit-tests-coverage-report:
{{> require-unit-tests-coverage.yml}}
- job-unit-tests-gas-report:
{{> require-prepare.yml}}
{{> require-unit-tests.yml}}
- job-test-deploy-script:
{{> require-prepare.yml}}

Expand Down
2 changes: 1 addition & 1 deletion codechecks.unit.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
checks:
- name: eth-gas-reporter/codechecks
options:
name: unit-test-gas-report
name: unit-test-gas-report-unoptimized
settings:
branches:
- develop
Expand Down
1 change: 1 addition & 0 deletions hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ module.exports = {
gasReporter: {
enabled: false,
showTimeSpent: true,
gasPrice: 20,
currency: 'USD',
maxMethodDiff: 25, // CI will fail if gas usage is > than this %
outputFile: 'test-gas-used.log',
Expand Down
125 changes: 125 additions & 0 deletions hardhat/tasks/task-test-merge-gas-reports.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
const fs = require('fs');
const path = require('path');
const { gray } = require('chalk');
const { task } = require('hardhat/config');
const { globSync } = require('hardhat/internal/util/glob');
const uniq = require('lodash.uniq');

/**
* Task for merging multiple gasReporterOuput.json files generated by eth-gas-reporter
* This task is necessary when we want to generate different parts of the reports
* parallelized on different jobs, then merge the results and upload it to codechecks.
* Gas Report JSON file schema: https://github.com/cgewecke/eth-gas-reporter/blob/master/docs/gasReporterOutput.md
*/

task('test:merge-gas-reports', 'Merge several gasReporterOuput.json files into one')
.addOptionalParam('output', 'Target file to save the merged report', 'gasReporterOutput.json')
.addVariadicPositionalParam(
'input',
'A list of gasReporterOutput.json files generated by eth-gas-reporter. Files can be defined using glob patterns'
)
.setAction(async taskArguments => {
const output = path.resolve(taskArguments.output);

// Parse input files and calculate glob patterns
const input = uniq(taskArguments.input.map(globSync).flat()).map(inputFile =>
path.resolve(inputFile)
);

if (input.length === 0) {
throw new Error(`No files found for the given input: ${taskArguments.input.join(' ')}`);
}

console.log(gray(`Merging ${input.length} input files:`));
input.forEach(inputFile => {
console.log(gray(' - ', inputFile));
});

console.log(gray('\nOutput: ', output));

const result = {
namespace: null,
config: null,
info: {
methods: {},
deployments: [],
blockLimit: null,
},
};

input.forEach(inputFile => {
const report = JSON.parse(fs.readFileSync(inputFile, 'utf-8'));

if (!report.config) {
throw new Error(`Missing "config" property on ${inputFile}`);
}

if (!result.config) result.config = report.config;

if (!result.namespace) {
result.namespace = report.namespace;
}

if (result.namespace !== report.namespace) {
throw new Error('Cannot merge reports with different namespaces');
}

// Update config.gasPrice only if the newer one has a bigger number
if (typeof report.config.gasPrice === 'number') {
if (
typeof result.config.gasPrice !== 'number' ||
result.config.gasPrice < report.config.gasPrice
) {
result.config.gasPrice = report.config.gasPrice;
}
} else {
result.config.gasPrice = report.config.gasPrice;
}

if (!report.info || typeof report.info.blockLimit !== 'number') {
throw new Error(`Invalid "info" property on ${inputFile}`);
}

if (!result.info.blockLimit) {
result.info.blockLimit = report.info.blockLimit;
} else if (result.info.blockLimit !== report.info.blockLimit) {
throw new Error('"info.blockLimit" should be the same on all reports');
}

if (!report.info.methods) {
throw new Error(`Missing "info.methods" property on ${inputFile}`);
}

// Merge info.methods objects
Object.entries(report.info.methods).forEach(([key, value]) => {
if (!result.info.methods[key]) {
result.info.methods[key] = value;
return;
}

result.info.methods[key].gasData = [
...result.info.methods[key].gasData,
...report.info.methods[key].gasData,
].sort((a, b) => a - b);

result.info.methods[key].numberOfCalls += report.info.methods[key].numberOfCalls;
});

if (!Array.isArray(report.info.deployments)) {
throw new Error(`Invalid "info.deployments" property on ${inputFile}`);
}

// Merge info.deployments objects
report.info.deployments.forEach(deployment => {
const current = result.info.deployments.find(d => d.name === deployment.name);

if (current) {
current.gasData = [...current.gasData, ...deployment.gasData].sort((a, b) => a - b);
} else {
result.info.deployments.push(deployment);
}
});
});

fs.writeFileSync(output, JSON.stringify(result), 'utf-8');
});
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
"fork": "node --max-old-space-size=4096 ./node_modules/.bin/hardhat node --target-network mainnet",
"test": "hardhat test",
"describe": "hardhat describe",
"test:gas": "hardhat test --gas --optimizer || cat test-gas-used.log",
"test:deployments": "mocha test/deployments -- --timeout 60000",
"test:etherscan": "node test/etherscan",
"test:publish": "concurrently --kill-others --success first \"npx hardhat node > /dev/null\" \"wait-port 8545 && mocha test/publish --bail --timeout 240000\""
Expand Down