Files
moli/.github/workflows/ci-regression-comment.yml
ldm0 833cdbc558 ci: include WebMainBench in the PR regression report
Add completion, failure, panic, crash, and timeout counts to the existing aggregate PR comment. Validate summary counts, bound failure details, and keep missing or incomplete evidence visible with a link to the source run.
2026-09-24 19:22:52 +08:00

196 lines
7.9 KiB
YAML

name: CI Regression Report
on:
workflow_run:
workflows: [CI]
types: [in_progress]
concurrency:
group: ci-regression-report-${{ github.event.workflow_run.pull_requests[0].number || github.event.workflow_run.id }}
cancel-in-progress: true
# This trusted default-branch workflow never executes code from the PR. It waits
# for immutable v4 artifacts, parses only bounded fields, and upserts one report.
permissions:
actions: read
contents: read
pull-requests: write
jobs:
comment:
name: Publish aggregate regression report
if: >-
github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.pull_requests[0].head.repo.id == github.event.repository.id &&
github.event.workflow_run.actor.login != 'dependabot[bot]'
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- name: Checkout trusted report renderer
uses: actions/checkout@v4
with:
persist-credentials: false
ref: ${{ github.event.repository.default_branch }}
- name: Wait for aggregate evidence
id: wait
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
env:
ARTIFACT_NAMES: >-
["release-regression-results","frontend-differential-results","agent-episode-results","runtime-contract-results","cdp-smoke-diagnostics","webmainbench-results"]
with:
retries: 3
script: |
const helper = require('./.github/scripts/wait-for-workflow-artifact.cjs');
await helper.waitForWorkflowArtifacts({
github,
context,
core,
artifactNames: JSON.parse(process.env.ARTIFACT_NAMES),
});
- name: Download release regression evidence
if: contains(fromJSON(steps.wait.outputs.available_artifacts), 'release-regression-results')
continue-on-error: true
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: release-regression-results
path: ci-regression-artifacts/release
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }}
- name: Download frontend differential evidence
if: contains(fromJSON(steps.wait.outputs.available_artifacts), 'frontend-differential-results')
continue-on-error: true
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: frontend-differential-results
path: ci-regression-artifacts/frontend
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }}
- name: Download agent episode evidence
if: contains(fromJSON(steps.wait.outputs.available_artifacts), 'agent-episode-results')
continue-on-error: true
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: agent-episode-results
path: ci-regression-artifacts/agent
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }}
- name: Download runtime contract evidence
if: contains(fromJSON(steps.wait.outputs.available_artifacts), 'runtime-contract-results')
continue-on-error: true
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: runtime-contract-results
path: ci-regression-artifacts/runtime
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }}
- name: Download CDP smoke evidence
if: contains(fromJSON(steps.wait.outputs.available_artifacts), 'cdp-smoke-diagnostics')
continue-on-error: true
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: cdp-smoke-diagnostics
path: ci-regression-artifacts/cdp
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }}
- name: Download WebMainBench evidence
if: contains(fromJSON(steps.wait.outputs.available_artifacts), 'webmainbench-results')
continue-on-error: true
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: webmainbench-results
path: ci-regression-artifacts/webmainbench
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }}
- name: Install Node.js
if: steps.wait.outputs.conclusion != 'cancelled'
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 24.15.0
- name: Render trusted aggregate report
if: steps.wait.outputs.conclusion != 'cancelled'
env:
RUN_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}
CONCLUSION: ${{ steps.wait.outputs.conclusion || 'in_progress' }}
run: >-
node .github/scripts/render-ci-regression-comment.cjs
--release ci-regression-artifacts/release
--frontend ci-regression-artifacts/frontend
--agent ci-regression-artifacts/agent
--runtime ci-regression-artifacts/runtime
--cdp ci-regression-artifacts/cdp
--webmainbench ci-regression-artifacts/webmainbench
--run-url "$RUN_URL"
--conclusion "$CONCLUSION"
--output ci-regression-comment.md
- name: Publish Actions report
if: steps.wait.outputs.conclusion != 'cancelled'
run: cat ci-regression-comment.md >> "$GITHUB_STEP_SUMMARY"
- name: Post PR regression comment
if: steps.wait.outputs.conclusion != 'cancelled'
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
env:
COMMENT_PATH: ci-regression-comment.md
with:
script: |
const fs = require('fs');
const run = context.payload.workflow_run;
const association = run.pull_requests?.[0];
if (!association) {
core.notice('No pull request is associated with this workflow run.');
return;
}
const pull = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: association.number,
});
if (pull.data.head.sha !== association.head.sha) {
core.notice('Skipping a stale CI regression report for an older PR head.');
return;
}
const body = fs.readFileSync(process.env.COMMENT_PATH, 'utf8');
const marker = '<!-- moli-ci-regression-report -->';
if (!body.includes(marker) || Buffer.byteLength(body, 'utf8') > 32 * 1024) {
core.setFailed('Rendered CI regression report is missing its marker or exceeds 32 KiB.');
return;
}
const comments = await github.paginate(github.rest.issues.listComments, {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: association.number,
per_page: 100,
});
const existing = comments.find(
(comment) =>
comment.user?.login === 'github-actions[bot]' &&
comment.body?.includes(marker)
);
if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: association.number,
body,
});
}