Skip to content

Commit

Permalink
fix: markdown breaking lines format (#97)
Browse files Browse the repository at this point in the history
* chore: change format to table, breaking lines reliable, add tests

* chore: github actions standard template-like

* chore: github actions standard template-like, more tests

* chore: adjustments

* chore: adjustments readme

* fix: tests and use templates for concat

* fix: tests cleanup

* fix: tests packaging

* fix: prefix with npx to build

* fix: add pr comment suggestions
  • Loading branch information
yamilmedina authored May 2, 2024
1 parent daffe66 commit 0b1ff50
Show file tree
Hide file tree
Showing 12 changed files with 274 additions and 55 deletions.
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,39 @@
# kotlinx-benchmark-table-action
An Action to take info from kotlinx-benchmark outputs and display them in a table as a pull request comment

Check [action.yml](action.yml) for a description of inputs and outputs.

### Configuration sample

1. As a GitHub Summary check:

```yml
- name: Create Benchmark Table
id: benchmark-table
uses: boswelja/[email protected]
with:
benchmark-results: ./benchmarks/build/reports/benchmarks/main/**/jvm.json
- name: Post Results
run: |
echo '## Benchmarks results ⏱️' >> $GITHUB_STEP_SUMMARY
echo '${{steps.benchmark-table.outputs.benchmark-table}}️' >> $GITHUB_STEP_SUMMARY
```
2. As a GitHub PR comment (Assuming the action is running on a GitHub runners):
```yml
- name: Create Benchmark Table
id: benchmark-table
uses: boswelja/[email protected]
with:
benchmark-results: ./benchmarks/build/reports/benchmarks/main/**/jvm.json
- name: Post Results
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_HEAD_REF: ${{github.head_ref}}
run: |
gh pr comment "$GH_HEAD_REF" --body "
## Benchmarks from last commit:
${{steps.benchmark-table.outputs.benchmark-table}}
"
```
4 changes: 4 additions & 0 deletions __tests__/fixtures/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
| Benchmark | Score | Error |
| --------- | ----- | ----- |
| com.benchmarks.MessagesBenchmark.messageInsertionBenchmark | 1.782ops/s | 0.223ops/s |
| com.benchmarks.MessagesBenchmark.queryMessagesBenchmark | 50.457ops/s | 3.394ops/s |
124 changes: 124 additions & 0 deletions __tests__/fixtures/sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
[
{
"jmhVersion" : "1.37",
"benchmark" : "com.benchmarks.MessagesBenchmark.messageInsertionBenchmark",
"mode" : "thrpt",
"threads" : 1,
"forks" : 1,
"jvm" : "/Users/theUser/.sdkman/candidates/java/17.0.7-tem/bin/java",
"jvmArgs" : [
"-Dfile.encoding=UTF-8",
"-Duser.country=DE",
"-Duser.language=en",
"-Duser.variant"
],
"jdkVersion" : "17.0.7",
"vmName" : "OpenJDK 64-Bit Server VM",
"vmVersion" : "17.0.7+7",
"warmupIterations" : 1,
"warmupTime" : "10 s",
"warmupBatchSize" : 1,
"measurementIterations" : 10,
"measurementTime" : "1 s",
"measurementBatchSize" : 1,
"primaryMetric" : {
"score" : 1.7823356802696022,
"scoreError" : 0.2226165791748437,
"scoreConfidence" : [
1.5597191010947584,
2.0049522594444458
],
"scorePercentiles" : {
"0.0" : 1.4878886330237069,
"50.0" : 1.8424420821050043,
"90.0" : 1.9010407215835783,
"95.0" : 1.902112609711454,
"99.0" : 1.902112609711454,
"99.9" : 1.902112609711454,
"99.99" : 1.902112609711454,
"99.999" : 1.902112609711454,
"99.9999" : 1.902112609711454,
"100.0" : 1.902112609711454
},
"scoreUnit" : "ops/s",
"rawData" : [
[
1.8012946805516465,
1.5654607694063567,
1.4878886330237069,
1.7169346383277355,
1.8913937284326974,
1.8699750264835213,
1.8876201422086203,
1.902112609711454,
1.814909137726487,
1.8857674368237995
]
]
},
"secondaryMetrics" : {
}
},
{
"jmhVersion" : "1.37",
"benchmark" : "com.benchmarks.MessagesBenchmark.queryMessagesBenchmark",
"mode" : "thrpt",
"threads" : 1,
"forks" : 1,
"jvm" : "/Users/theUser/.sdkman/candidates/java/17.0.7-tem/bin/java",
"jvmArgs" : [
"-Dfile.encoding=UTF-8",
"-Duser.country=DE",
"-Duser.language=en",
"-Duser.variant"
],
"jdkVersion" : "17.0.7",
"vmName" : "OpenJDK 64-Bit Server VM",
"vmVersion" : "17.0.7+7",
"warmupIterations" : 1,
"warmupTime" : "10 s",
"warmupBatchSize" : 1,
"measurementIterations" : 10,
"measurementTime" : "1 s",
"measurementBatchSize" : 1,
"primaryMetric" : {
"score" : 50.45665058195113,
"scoreError" : 3.3937165496625408,
"scoreConfidence" : [
47.06293403228859,
53.85036713161367
],
"scorePercentiles" : {
"0.0" : 44.74868687531958,
"50.0" : 51.19678172516677,
"90.0" : 52.28606095305461,
"95.0" : 52.29307176896627,
"99.0" : 52.29307176896627,
"99.9" : 52.29307176896627,
"99.99" : 52.29307176896627,
"99.999" : 52.29307176896627,
"99.9999" : 52.29307176896627,
"100.0" : 52.29307176896627
},
"scoreUnit" : "ops/s",
"rawData" : [
[
52.22296360984965,
50.878313350724106,
51.958061150989145,
49.564829078021425,
51.53162687896872,
51.51525009960944,
52.29307176896627,
44.74868687531958,
50.251918533264735,
49.601784473798226
]
]
},
"secondaryMetrics" : {
}
}
]


13 changes: 13 additions & 0 deletions __tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import * as main from '../src/main'

// Mock the action's entrypoint
const runMock = jest.spyOn(main, 'run').mockImplementation()

describe('index', () => {
it('calls run when imported', async () => {
// eslint-disable-next-line @typescript-eslint/no-require-imports
require('../src/index')

expect(runMock).toHaveBeenCalled()
})
})
18 changes: 18 additions & 0 deletions __tests__/tablebuilder.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as tablebuild from '../src/tablebuilder'
import { Benchmark } from '../src/benchmark'
import { debug } from '@actions/core'
import sample from './fixtures/sample.json'
import { readFileSync } from 'fs'

const runMock = jest.spyOn(tablebuild, 'buildBenchmarkTable')

describe('tablebuilder', () => {
it('maps the parsed benchmarks into markdown', () => {
let benchmarks: Benchmark[] = JSON.parse(JSON.stringify(sample))
debug("Num of benchmarks: " + benchmarks.length)
let result = tablebuild.buildBenchmarkTable(benchmarks)
let output = readFileSync(__dirname + '/fixtures/output.txt')

expect(result).toBe(output.toString())
})
})
2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
"description": "An Action to take info from kotlinx-benchmark outputs and display them in a table as a pull request comment",
"main": "dist/index.js",
"scripts": {
"build": "ncc build src/main.ts -m -o dist/",
"test": "npx jest"
"build": "npx ncc build src/index.ts -m -o dist/",
"test": "npx jest",
"all": "npm run test && npm run build"
},
"repository": {
"type": "git",
Expand Down Expand Up @@ -40,7 +41,7 @@
"ts"
],
"testMatch": [
"__tests__/**/*.test.ts"
"**/*.test.ts"
],
"testPathIgnorePatterns": [
"/node_modules/",
Expand All @@ -50,4 +51,4 @@
"^.+\\.ts$": "ts-jest"
}
}
}
}
56 changes: 28 additions & 28 deletions src/benchmark.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
import { readFileSync } from "fs";
import { readFileSync } from "fs"

export interface Benchmark {
jmhVersion: string;
benchmark: string;
mode: string;
threads: number;
forks: number;
jvm: string;
jvmArgs: string[];
jdkVersion: string;
vmName: string;
vmVersion: string;
warmupIterations: number;
warmupTime: string;
warmupBatchSize: number;
measurementIterations: number;
measurementTime: string;
measurementBatchSize: number;
primaryMetric: PrimaryMetric;
secondaryMetrics: SecondaryMetrics;
jmhVersion: string
benchmark: string
mode: string
threads: number
forks: number
jvm: string
jvmArgs: string[]
jdkVersion: string
vmName: string
vmVersion: string
warmupIterations: number
warmupTime: string
warmupBatchSize: number
measurementIterations: number
measurementTime: string
measurementBatchSize: number
primaryMetric: PrimaryMetric
secondaryMetrics: SecondaryMetrics
}

export interface PrimaryMetric {
score: number;
scoreError: number;
scoreConfidence: number[];
scorePercentiles: { [key: string]: number };
scoreUnit: string;
rawData: Array<number[]>;
score: number
scoreError: number
scoreConfidence: number[]
scorePercentiles: { [key: string]: number }
scoreUnit: string
rawData: Array<number[]>
}

export interface SecondaryMetrics {
}

function benchmarksFromFile(filePath: string): Benchmark[] {
let rawData = readFileSync(filePath);
let benchmarks: Benchmark[] = JSON.parse(rawData.toString());
return benchmarks;
let rawData = readFileSync(filePath)
let benchmarks: Benchmark[] = JSON.parse(rawData.toString())
return benchmarks
}

export function mapFilesToBenchmarks(files: string[]): Benchmark[] {
Expand Down
7 changes: 7 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* The entrypoint for the action.
*/
import { run } from './main'

// eslint-disable-next-line @typescript-eslint/no-floating-promises
run()
16 changes: 7 additions & 9 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { getInput, setOutput, setFailed, exportVariable, debug, info } from '@actions/core';
import { glob } from "glob";
import { mapFilesToBenchmarks } from "./benchmark";
import { buildBenchmarkTable } from "./tablebuilder";
import { getInput, setOutput, setFailed, exportVariable, debug, info } from '@actions/core'
import { glob } from "glob"
import { mapFilesToBenchmarks } from "./benchmark"
import { buildBenchmarkTable } from "./tablebuilder"

function main() {
export function run() {
// Get the result json path
var benchmarkResultPath = getInput("benchmark-results", { required: true })
let benchmarkResultPath = getInput("benchmark-results", { required: true })
debug("Getting results matching path " + benchmarkResultPath)

try {
Expand All @@ -18,12 +18,10 @@ function main() {
}

// Build and output the table
let table = buildBenchmarkTable(benchmarks);
let table = buildBenchmarkTable(benchmarks)
setOutput("benchmark-table", table);
} catch {
setFailed("Failed to get benchmarks")
return
}
}

main();
17 changes: 8 additions & 9 deletions src/tablebuilder.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Benchmark } from "./benchmark";
import { Benchmark } from "./benchmark"

function formattedScoreFor(benchmark: Benchmark): string {
return benchmark.primaryMetric.score.toFixed(3) + benchmark.primaryMetric.scoreUnit
Expand All @@ -9,13 +9,12 @@ function formattedErrorFor(benchmark: Benchmark): string {
}

export function buildBenchmarkTable(benchmarks: Benchmark[]): string {
var tableString = "| Benchmark | Score | Error |\n" +
"| --------- | ----- | ----- |\n";

let tableString = `| Benchmark | Score | Error |`
tableString += `\n`
tableString += `| --------- | ----- | ----- |`
benchmarks.forEach(function (benchmark) {
tableString +=
"| " + benchmark.benchmark + " | " + formattedScoreFor(benchmark) + " | " + formattedErrorFor(benchmark) + " |\n"
});

return tableString;
tableString += `\n`
tableString += `| ${benchmark.benchmark} | ${formattedScoreFor(benchmark)} | ${formattedErrorFor(benchmark)} |`
})
return tableString
}
Loading

0 comments on commit 0b1ff50

Please sign in to comment.