Repository navigation
160 lines (152 loc) Β· 5.96 KB
/
Copy pathbenchmark.yml
File metadata and controls
160 lines (152 loc) Β· 5.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
name: Performance Benchmark
on:
pull_request:
branches: [trunk]
workflow_dispatch:
permissions:
contents: read
concurrency:
group: benchmark-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
BENCHMARK_GATE_MODE: enforce
jobs:
classify:
name: classify
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
pull-requests: read
outputs:
applicable: ${{ steps.changed.outputs.applicable }}
steps:
- name: Classify benchmark changes
id: changed
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
if (context.eventName === 'workflow_dispatch') {
core.setOutput('applicable', 'true');
return;
}
const files = await github.paginate(github.rest.pulls.listFiles, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
per_page: 100,
});
const applicable = files.some(({ filename }) =>
/^packages\/[^/]+\/src\//.test(filename) ||
filename.startsWith('tsconfig/') ||
filename.startsWith('benchmarks/') ||
filename.startsWith('ci-reports/benchmark/') ||
filename === 'scripts/bench-threshold-check.mts' ||
filename === 'scripts/benchmark-readiness-report.mts' ||
filename === 'scripts/post-benchmark-comment.mjs' ||
filename.startsWith('scripts/tests/') ||
filename === 'package.json' ||
filename === 'vitest.config.ts' ||
filename === 'vitest.config.bench.ts' ||
filename === 'tsconfig.json' ||
filename === 'pnpm-lock.yaml' ||
filename === '.github/workflows/benchmark.yml'
);
core.setOutput('applicable', String(applicable));
benchmark:
name: benchmark
needs: classify
if: needs.classify.outputs.applicable == 'true'
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: read
steps:
- name: Checkout pull request revision
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
- uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4.3.0
with:
version: "2026.9.13"
cache: false
- run: pnpm install --frozen-lockfile
- name: Prepare benchmark dependencies
run: pnpm bench:prepare
- name: Run benchmarks with threshold check
id: bench
run: pnpm tracked-files:guard --recovery 'pnpm bench:update' -- pnpm bench:check --output-json=benchmark-result.json
continue-on-error: true
env:
CI: true
- name: Publish benchmark enforce-readiness report
id: readiness
if: always()
continue-on-error: true
shell: bash
env:
BENCHMARK_STEP_OUTCOME: ${{ steps.bench.outcome }}
BENCHMARK_STEP_CONCLUSION: ${{ steps.bench.conclusion }}
run: |
set +e
pnpm bench:readiness --input=benchmark-result.json --output=ci-reports/benchmark/summary.md --variance-evidence=ci-reports/benchmark/latest-five-green-runs.md
readiness_exit=$?
cat ci-reports/benchmark/summary.md >> "$GITHUB_STEP_SUMMARY" || true
exit "$readiness_exit"
- name: Upload benchmark readiness report
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: benchmark-readiness-report-${{ github.run_id }}-${{ github.run_attempt }}
path: |
benchmark-result.json
ci-reports/benchmark/summary.md
ci-reports/benchmark/latest-five-green-runs.md
if-no-files-found: warn
- name: Fail if benchmark enforcement failed
if: env.BENCHMARK_GATE_MODE == 'enforce' && (steps.bench.outcome == 'failure' || steps.readiness.outcome == 'failure')
run: exit 1
benchmark-gate:
name: benchmark-gate
needs: [classify, benchmark]
if: ${{ always() }}
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
pull-requests: read
steps:
- name: Require current pull request revision
if: github.event_name == 'pull_request'
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const { data: pullRequest } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
});
if (pullRequest.head.sha !== context.payload.pull_request.head.sha) {
core.setFailed(`Benchmark evidence targets stale revision ${context.payload.pull_request.head.sha}; current head is ${pullRequest.head.sha}.`);
}
- name: Enforce benchmark result
shell: bash
env:
CLASSIFY_RESULT: ${{ needs.classify.result }}
BENCHMARK_APPLICABLE: ${{ needs.classify.outputs.applicable }}
BENCHMARK_RESULT: ${{ needs.benchmark.result }}
run: |
if [ "$CLASSIFY_RESULT" != "success" ]; then
echo "::error::Benchmark change classification did not succeed."
exit 1
fi
if [ "$BENCHMARK_APPLICABLE" != "true" ]; then
echo "No benchmark-relevant files changed; benchmark gate passes as not applicable."
exit 0
fi
if [ "$BENCHMARK_RESULT" != "success" ]; then
echo "::error::Benchmark verification concluded $BENCHMARK_RESULT."
exit 1
fi
echo "Benchmark verification passed for the current pull request revision."