Skip to content

Commit 1a37ca3

Browse files
committed
feat(showcase): Check Run button UX for eval trigger
New showcase_eval_check.yml creates a Check Run with "Run Showcase Eval" action button on every PR. Modified showcase_eval.yml adds workflow_dispatch trigger with dispatch-gate job, Check Run update in post-result, and devops bot token for Checks API calls.
1 parent 630c741 commit 1a37ca3

2 files changed

Lines changed: 183 additions & 11 deletions

File tree

.github/workflows/showcase_eval.yml

Lines changed: 137 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,24 @@ name: "showcase / eval"
2323
on:
2424
issue_comment:
2525
types: [created]
26+
workflow_dispatch:
27+
inputs:
28+
pr_number:
29+
description: "PR number to evaluate"
30+
required: true
31+
type: string
32+
check_run_id:
33+
description: "Check Run ID to update with results"
34+
required: false
35+
type: string
36+
level:
37+
description: "Eval depth level"
38+
required: false
39+
default: "d5"
40+
type: string
2641

2742
concurrency:
28-
group: showcase-eval-${{ github.event.issue.number }}
43+
group: showcase-eval-${{ github.event.inputs.pr_number || github.event.issue.number || github.run_id }}
2944
cancel-in-progress: true
3045

3146
permissions:
@@ -197,14 +212,55 @@ jobs:
197212
].join('\n'),
198213
});
199214
215+
dispatch-gate:
216+
if: github.event_name == 'workflow_dispatch'
217+
runs-on: ubuntu-latest
218+
timeout-minutes: 2
219+
permissions:
220+
contents: read
221+
pull-requests: read
222+
outputs:
223+
pr_sha: ${{ steps.resolve.outputs.sha }}
224+
pr_number: ${{ github.event.inputs.pr_number }}
225+
level: ${{ github.event.inputs.level || 'd5' }}
226+
scope_flag: "--scope affected"
227+
scope_display: "affected"
228+
check_run_id: ${{ github.event.inputs.check_run_id }}
229+
steps:
230+
- name: Resolve PR HEAD SHA
231+
id: resolve
232+
uses: actions/github-script@v7
233+
with:
234+
script: |
235+
const pr = await github.rest.pulls.get({
236+
owner: context.repo.owner,
237+
repo: context.repo.repo,
238+
pull_number: Number(process.env.PR_NUMBER),
239+
});
240+
if (pr.data.state !== 'open') {
241+
core.setFailed(`PR #${process.env.PR_NUMBER} is not open`);
242+
return;
243+
}
244+
core.setOutput('sha', pr.data.head.sha);
245+
env:
246+
PR_NUMBER: ${{ github.event.inputs.pr_number }}
247+
200248
eval:
201-
needs: gate
249+
needs: [gate, dispatch-gate]
250+
if: always() && (needs.gate.result == 'success' || needs.dispatch-gate.result == 'success')
202251
runs-on: depot-ubuntu-24.04-16
203252
timeout-minutes: 45
204253

205254
permissions:
206255
contents: read
207256

257+
env:
258+
PR_SHA: ${{ needs.gate.outputs.pr_sha || needs.dispatch-gate.outputs.pr_sha }}
259+
PR_NUMBER: ${{ needs.gate.outputs.pr_number || needs.dispatch-gate.outputs.pr_number }}
260+
EVAL_LEVEL: ${{ needs.gate.outputs.level || needs.dispatch-gate.outputs.level || 'd5' }}
261+
EVAL_SCOPE_FLAG: ${{ needs.gate.outputs.scope_flag || needs.dispatch-gate.outputs.scope_flag }}
262+
CHECK_RUN_ID: ${{ needs.dispatch-gate.outputs.check_run_id || '' }}
263+
208264
outputs:
209265
result_json: ${{ steps.run-eval.outputs.result_json }}
210266
exit_code: ${{ steps.run-eval.outputs.exit_code }}
@@ -214,7 +270,7 @@ jobs:
214270
- name: Checkout PR HEAD
215271
uses: actions/checkout@v4
216272
with:
217-
ref: ${{ needs.gate.outputs.pr_sha }}
273+
ref: ${{ env.PR_SHA }}
218274
fetch-depth: 0
219275
persist-credentials: false
220276

@@ -234,9 +290,6 @@ jobs:
234290

235291
- name: Run showcase eval
236292
id: run-eval
237-
env:
238-
EVAL_LEVEL: ${{ needs.gate.outputs.level }}
239-
EVAL_SCOPE_FLAG: ${{ needs.gate.outputs.scope_flag }}
240293
run: |
241294
set -o pipefail
242295
@@ -296,14 +349,15 @@ jobs:
296349
if-no-files-found: ignore
297350

298351
post-result:
299-
needs: [gate, eval]
300-
if: always() && needs.gate.result == 'success'
352+
needs: [gate, dispatch-gate, eval]
353+
if: always() && (needs.gate.result == 'success' || needs.dispatch-gate.result == 'success')
301354
runs-on: ubuntu-latest
302355
timeout-minutes: 5
303356

304357
permissions:
305358
pull-requests: write
306359
issues: write
360+
checks: write
307361

308362
steps:
309363
- name: Post eval results to PR
@@ -313,9 +367,9 @@ jobs:
313367
RESULT_JSON: ${{ needs.eval.outputs.result_json }}
314368
STDERR_EXCERPT: ${{ needs.eval.outputs.stderr_excerpt }}
315369
EXIT_CODE: ${{ needs.eval.outputs.exit_code }}
316-
LEVEL: ${{ needs.gate.outputs.level }}
317-
SCOPE_DISPLAY: ${{ needs.gate.outputs.scope_display }}
318-
PR_NUMBER: ${{ needs.gate.outputs.pr_number }}
370+
LEVEL: ${{ needs.gate.outputs.level || needs.dispatch-gate.outputs.level || 'd5' }}
371+
SCOPE_DISPLAY: ${{ needs.gate.outputs.scope_display || needs.dispatch-gate.outputs.scope_display || 'affected' }}
372+
PR_NUMBER: ${{ needs.gate.outputs.pr_number || needs.dispatch-gate.outputs.pr_number }}
319373
with:
320374
script: |
321375
const evalStatus = process.env.EVAL_STATUS;
@@ -492,3 +546,75 @@ jobs:
492546
issue_number: prNumber,
493547
body,
494548
});
549+
550+
- name: Generate devops-bot token
551+
id: bot-token
552+
if: needs.dispatch-gate.outputs.check_run_id != ''
553+
uses: actions/create-github-app-token@v2
554+
with:
555+
app-id: 1108748
556+
private-key: ${{ secrets.DEVOPS_BOT_PRIVATE_KEY }}
557+
558+
- name: Update Check Run with results
559+
if: needs.dispatch-gate.outputs.check_run_id != ''
560+
uses: actions/github-script@v7
561+
with:
562+
github-token: ${{ steps.bot-token.outputs.token }}
563+
script: |
564+
const checkRunId = Number(process.env.CHECK_RUN_ID);
565+
const resultJson = process.env.RESULT_JSON || '{}';
566+
const evalStatus = '${{ needs.eval.result }}';
567+
568+
let conclusion = 'failure';
569+
let title = 'Showcase Eval — error';
570+
let summary = 'The evaluation encountered an error.';
571+
572+
try {
573+
const results = JSON.parse(resultJson);
574+
const s = results.summary || {};
575+
576+
if (evalStatus === 'success' && s.fail === 0) {
577+
conclusion = 'success';
578+
title = `${s.pass}/${s.total} passed (${(s.duration_ms / 1000).toFixed(1)}s)`;
579+
} else if (s.total === 0) {
580+
conclusion = 'neutral';
581+
title = 'No showcase integrations affected';
582+
} else {
583+
conclusion = 'failure';
584+
title = `${s.fail} failed, ${s.pass} passed`;
585+
}
586+
587+
const lines = ['## Eval Results\n'];
588+
lines.push('| Integration | Status |');
589+
lines.push('|-------------|--------|');
590+
if (results.results) {
591+
for (const [slug, tests] of Object.entries(results.results)) {
592+
const statuses = Object.values(tests);
593+
const pass = statuses.filter(t => t.status === 'pass').length;
594+
const total = statuses.length;
595+
const icon = pass === total ? '✅' : '❌';
596+
lines.push(`| ${slug} | ${icon} ${pass}/${total} |`);
597+
}
598+
}
599+
lines.push(`\n**Total:** ${s.pass} passed, ${s.fail} failed, ${s.skip} skipped (${(s.duration_ms / 1000).toFixed(1)}s)`);
600+
summary = lines.join('\n');
601+
} catch (e) {
602+
summary = `Parse error: ${e.message}`;
603+
}
604+
605+
await github.rest.checks.update({
606+
owner: context.repo.owner,
607+
repo: context.repo.repo,
608+
check_run_id: checkRunId,
609+
status: 'completed',
610+
conclusion,
611+
output: { title, summary },
612+
actions: [{
613+
label: 'Re-run Eval',
614+
description: 'Run D5 evaluation',
615+
identifier: 'run-eval',
616+
}],
617+
});
618+
env:
619+
CHECK_RUN_ID: ${{ needs.dispatch-gate.outputs.check_run_id }}
620+
RESULT_JSON: ${{ needs.eval.outputs.result_json }}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: "Showcase: Eval Check"
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened]
6+
7+
permissions:
8+
contents: read
9+
10+
jobs:
11+
create-check:
12+
runs-on: ubuntu-latest
13+
timeout-minutes: 2
14+
steps:
15+
- name: Generate devops-bot token
16+
id: bot-token
17+
uses: actions/create-github-app-token@v2
18+
with:
19+
app-id: 1108748
20+
private-key: ${{ secrets.DEVOPS_BOT_PRIVATE_KEY }}
21+
22+
- name: Create Check Run
23+
uses: actions/github-script@v7
24+
with:
25+
github-token: ${{ steps.bot-token.outputs.token }}
26+
script: |
27+
await github.rest.checks.create({
28+
owner: context.repo.owner,
29+
repo: context.repo.repo,
30+
name: "Showcase Eval",
31+
head_sha: context.payload.pull_request.head.sha,
32+
status: "completed",
33+
conclusion: "neutral",
34+
external_id: String(context.payload.pull_request.number),
35+
output: {
36+
title: "Showcase Eval — click to run",
37+
summary: "Evaluates this PR against the showcase integration matrix.\n\n_For targeted runs, comment `/eval d5 slug1,slug2` on the PR._",
38+
},
39+
actions: [
40+
{
41+
label: "Run Showcase Eval",
42+
description: "Run D5 evaluation",
43+
identifier: "run-eval",
44+
},
45+
],
46+
});

0 commit comments

Comments
 (0)