@@ -25,125 +25,88 @@ env:
2525 # `/benchmark threshold=N` comment.
2626 DEFAULT_THRESHOLD_PCT : " 10"
2727
28- # One run per PR (cancel any in-progress run when a newer /benchmark arrives
29- # for the same PR). Scheduled runs are grouped by SHA so they don't fight
30- # with PR runs.
31- concurrency :
32- group : ${{ github.workflow }}-${{ github.event.issue.number || github.event.inputs.pr || github.sha }}
33- cancel-in-progress : true
28+ # NOTE: there is intentionally no workflow-level `concurrency:` block.
29+ # `issue_comment` events fire for *every* comment on every PR / issue,
30+ # including those from bots (e.g. sonarqubecloud). A workflow-level
31+ # `cancel-in-progress` group keyed on the PR number would cancel an
32+ # in-flight legitimate `/benchmark` run as soon as any unrelated bot
33+ # commented on the same PR. The per-PR concurrency rule is enforced on
34+ # the `jmh` job instead, so unrelated comment events leave the job
35+ # skipped without claiming the concurrency slot.
3436
3537jobs :
36- # Gate for `issue_comment` events. The job is *skipped* (not failed) for
37- # anything that isn't a real `/benchmark` request — bot comments,
38- # comments on plain issues, and comments that don't start with the
39- # slash-command. This is what keeps unrelated activity (SonarQube
40- # quality-gate replies, etc.) from littering the Actions tab with red
41- # failed runs.
42- #
43- # Only an actual `/benchmark` attempt by someone without write access
44- # makes the job run and fail loudly (with a -1 reaction on the
45- # comment) — that's intentional feedback for an unauthorized trigger.
46- #
47- # For `schedule` and `workflow_dispatch` events the job-level `if` is
48- # false → trigger-check is skipped → the `jmh` job's `if` allows it
49- # to run.
50- trigger-check :
51- if : |
52- github.event_name == 'issue_comment' &&
53- github.event.issue.pull_request != null &&
54- github.event.sender.type != 'Bot' &&
55- github.event.comment.user.type != 'Bot' &&
56- startsWith(github.event.comment.body, '/benchmark')
57- name : " Check /benchmark trigger"
58- runs-on : ubuntu-latest
38+ jmh :
39+ name : " Mininal JMH Benchmarks"
40+ runs-on : " ubuntu-latest"
41+ timeout-minutes : 30
5942 permissions :
43+ contents : read
6044 pull-requests : write
6145 issues : write
62- outputs :
63- pr_number : ${{ steps.resolve.outputs.pr_number }}
64- threshold : ${{ steps.resolve.outputs.threshold }}
46+ actions : read
47+ # Single fan-in filter, modelled on `.github/workflows/claude.yml`:
48+ # the job runs for the daily schedule, manual `workflow_dispatch`,
49+ # or a `/benchmark` slash-command from a non-bot repo collaborator
50+ # on a pull request. Bot comments and chat comments leave the job
51+ # skipped — no failed run, no notification, no concurrency
52+ # collision.
53+ if : |
54+ startsWith(github.repository, 'ClickHouse/') &&
55+ (
56+ github.event_name == 'schedule' ||
57+ github.event_name == 'workflow_dispatch' ||
58+ (
59+ github.event_name == 'issue_comment' &&
60+ github.event.issue.pull_request != null &&
61+ github.event.sender.type != 'Bot' &&
62+ github.event.comment.user.type != 'Bot' &&
63+ startsWith(github.event.comment.body, '/benchmark') &&
64+ contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)
65+ )
66+ )
67+ # One running benchmark per PR (and per-SHA for the daily
68+ # schedule). Concurrency lives on this job, not on the workflow,
69+ # so unrelated comment events (which the job-level `if` filters
70+ # out) never claim the slot or cancel an in-flight run.
71+ concurrency :
72+ group : ${{ github.workflow }}-jmh-${{ github.event.issue.number || github.event.inputs.pr || github.sha }}
73+ cancel-in-progress : true
6574 steps :
66- - name : Check commenter is a collaborator
67- id : auth
68- if : contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)
69- run : echo "ok=true" >> "$GITHUB_OUTPUT"
70-
71- - name : Reject unauthorized trigger
72- if : steps.auth.outputs.ok != 'true'
73- env :
74- GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
75- run : |
76- gh api -X POST \
77- "repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions" \
78- -f content='-1' || true
79- echo "::error::User ${{ github.event.comment.user.login }} (author_association=${{ github.event.comment.author_association }}) is not allowed to run /benchmark."
80- exit 1
81-
82- - name : Acknowledge trigger
75+ - name : Acknowledge /benchmark trigger
76+ if : github.event_name == 'issue_comment'
8377 env :
8478 GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
8579 run : |
8680 gh api -X POST \
8781 "repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions" \
8882 -f content='rocket' || true
8983
90- - name : Resolve PR number and threshold
91- id : resolve
92- env :
93- COMMENT_BODY : ${{ github.event.comment.body }}
94- DEFAULT_THRESHOLD : ${{ env.DEFAULT_THRESHOLD_PCT }}
95- run : |
96- # Accept `/benchmark threshold=15` or `/benchmark threshold=7.5`.
97- # Anything else falls back to the workflow default.
98- T=$(printf '%s' "$COMMENT_BODY" | grep -oE 'threshold=[0-9]+(\.[0-9]+)?' | head -1 | cut -d= -f2 || true)
99- [ -z "$T" ] && T="$DEFAULT_THRESHOLD"
100- echo "pr_number=${{ github.event.issue.number }}" >> "$GITHUB_OUTPUT"
101- echo "threshold=$T" >> "$GITHUB_OUTPUT"
102-
103- jmh :
104- needs : [trigger-check]
105- # For `issue_comment` we require trigger-check to have *succeeded*
106- # (a real `/benchmark` from a collaborator). For every other event
107- # (`schedule`, `workflow_dispatch`) the trigger-check job is
108- # filtered out by its job-level `if`, so we require `skipped`.
109- # Without this split, bot comments that skip trigger-check would
110- # erroneously satisfy the `success || skipped` fan-in.
111- if : |
112- always() &&
113- startsWith(github.repository, 'ClickHouse/') &&
114- (
115- (github.event_name == 'issue_comment' && needs.trigger-check.result == 'success') ||
116- (github.event_name != 'issue_comment' && needs.trigger-check.result == 'skipped')
117- )
118- name : " Mininal JMH Benchmarks"
119- runs-on : " ubuntu-latest"
120- timeout-minutes : 30
121- permissions :
122- contents : read
123- pull-requests : write
124- actions : read
125- steps :
12684 - name : Resolve PR number and threshold
12785 id : pr
12886 env :
129- COMMENT_THRESHOLD : ${{ needs.trigger-check.outputs.threshold }}
87+ COMMENT_BODY : ${{ github.event.comment.body }}
88+ DISPATCH_PR : ${{ github.event.inputs.pr }}
13089 DISPATCH_THRESHOLD : ${{ github.event.inputs.threshold }}
13190 DEFAULT_THRESHOLD : ${{ env.DEFAULT_THRESHOLD_PCT }}
13291 run : |
13392 case "${{ github.event_name }}" in
13493 issue_comment)
135- echo "number=${{ needs.trigger-check.outputs.pr_number }}" >> "$GITHUB_OUTPUT"
136- echo "threshold=${COMMENT_THRESHOLD:-$DEFAULT_THRESHOLD}" >> "$GITHUB_OUTPUT"
94+ # Accept `/benchmark threshold=15` or `/benchmark threshold=7.5`.
95+ T=$(printf '%s' "$COMMENT_BODY" | grep -oE 'threshold=[0-9]+(\.[0-9]+)?' | head -1 | cut -d= -f2 || true)
96+ [ -z "$T" ] && T="$DEFAULT_THRESHOLD"
97+ echo "number=${{ github.event.issue.number }}" >> "$GITHUB_OUTPUT"
98+ echo "threshold=$T" >> "$GITHUB_OUTPUT"
13799 ;;
138100 workflow_dispatch)
139- echo "number=${{ github.event.inputs.pr }} " >> "$GITHUB_OUTPUT"
101+ echo "number=$DISPATCH_PR " >> "$GITHUB_OUTPUT"
140102 echo "threshold=${DISPATCH_THRESHOLD:-$DEFAULT_THRESHOLD}" >> "$GITHUB_OUTPUT"
141103 ;;
142104 *)
143105 echo "number=" >> "$GITHUB_OUTPUT"
144106 echo "threshold=$DEFAULT_THRESHOLD" >> "$GITHUB_OUTPUT"
145107 ;;
146108 esac
109+
147110 - name : Post "started" comment
148111 if : github.event_name == 'issue_comment' && steps.pr.outputs.number != ''
149112 env :
@@ -152,33 +115,40 @@ jobs:
152115 gh api -X POST \
153116 "repos/${{ github.repository }}/issues/${{ steps.pr.outputs.number }}/comments" \
154117 -f body="JMH benchmark run started: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" || true
118+
155119 - name : Check out Git repository
156120 uses : actions/checkout@v4
157121 with :
158122 ref : ${{ env.CHC_BRANCH }}
123+
159124 - name : Check out PR
160125 if : steps.pr.outputs.number != ''
161126 run : |
162127 git fetch --no-tags --prune --progress --no-recurse-submodules --depth=1 \
163128 origin pull/${{ steps.pr.outputs.number }}/merge:merged-pr && git checkout merged-pr
129+
164130 - name : Install JDK and Maven
165131 uses : actions/setup-java@v4
166132 with :
167133 distribution : " temurin"
168134 java-version : ${{ env.JAVA_VERSION }}
169135 cache : " maven"
136+
170137 - name : Build
171138 run : mvn --batch-mode --no-transfer-progress -Dj8 -DskipTests=true clean install
139+
172140 - name : Prepare Dataset
173141 run : |
174142 cd ./performance &&
175143 mvn --batch-mode --no-transfer-progress clean compile exec:exec -Dexec.executable=java \
176144 -Dexec.args="-classpath %classpath com.clickhouse.benchmark.data.DataSetGenerator -input sample_dataset.sql -name default -rows 100000"
145+
177146 - name : Run Benchmarks
178147 run : |
179148 cd ./performance &&
180149 mvn --batch-mode --no-transfer-progress clean compile exec:exec -Dexec.executable=java -Dexec.args="-classpath %classpath com.clickhouse.benchmark.BenchmarkRunner \
181150 -l 100000,10000 -m 3 -t 15 -b q,i -d file://default.csv"
151+
182152 - name : Upload test results
183153 uses : actions/upload-artifact@v4
184154 if : success()
0 commit comments