mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-20 14:30:41 +00:00
## Summary Replaces two separate PR comment workflows (bundle size + performance) with a single unified report that posts one combined comment per PR. ## Changes - **What**: New `pr-report.yaml` aggregator workflow triggers on both `CI: Size Data` and `CI: Performance Report` completions. Finds sibling workflow runs by PR head SHA. Renders combined report via `unified-report.js` (shells out to existing `size-report.js` and `perf-report.ts`). Sections show "pending" or "failed" placeholders when data is unavailable. - **Breaking**: Removes `pr-size-report.yaml` and `pr-perf-report.yaml`. Legacy `<!-- COMFYUI_FRONTEND_SIZE -->` and `<!-- COMFYUI_FRONTEND_PERF -->` comments are auto-cleaned on first run. - **Dependencies**: None ## Review Focus - Concurrency key uses `head_sha` so the later-completing workflow cancels the earlier report run, ensuring the final comment always has both sections. - Stale-run guard: verifies workflow_run SHA matches the live PR head before posting. - The `workflow_dispatch` re-trigger path from `pr-size-report.yaml` is not carried forward — the unified workflow handles re-trigger naturally via its dual-trigger design. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9911-feat-unified-PR-report-combining-bundle-size-and-runtime-perf-3236d73d365081baac1cce6f0d9244ac) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action <action@github.com>
221 lines
7.5 KiB
YAML
221 lines
7.5 KiB
YAML
name: 'PR: Unified Report'
|
|
|
|
on:
|
|
workflow_run:
|
|
workflows: ['CI: Size Data', 'CI: Performance Report']
|
|
types:
|
|
- completed
|
|
|
|
permissions:
|
|
contents: read
|
|
pull-requests: write
|
|
issues: write
|
|
actions: read
|
|
|
|
concurrency:
|
|
group: pr-report-${{ github.event.workflow_run.head_sha }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
comment:
|
|
runs-on: ubuntu-latest
|
|
if: >
|
|
github.repository == 'Comfy-Org/ComfyUI_frontend' &&
|
|
github.event.workflow_run.event == 'pull_request'
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
|
|
- name: Setup frontend
|
|
uses: ./.github/actions/setup-frontend
|
|
|
|
- name: Resolve PR from workflow_run context
|
|
id: pr-meta
|
|
uses: actions/github-script@v8
|
|
with:
|
|
script: |
|
|
let pr = context.payload.workflow_run.pull_requests?.[0];
|
|
if (!pr) {
|
|
const { data: prs } = await github.rest.repos.listPullRequestsAssociatedWithCommit({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
commit_sha: context.payload.workflow_run.head_sha,
|
|
});
|
|
pr = prs.find(p => p.state === 'open');
|
|
}
|
|
|
|
if (!pr) {
|
|
core.info('No open PR found for this workflow run — skipping.');
|
|
core.setOutput('skip', 'true');
|
|
return;
|
|
}
|
|
|
|
// Verify the workflow_run head SHA matches the current PR head
|
|
const { data: livePr } = await github.rest.pulls.get({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
pull_number: pr.number,
|
|
});
|
|
|
|
if (livePr.head.sha !== context.payload.workflow_run.head_sha) {
|
|
core.info(`Stale run: workflow SHA ${context.payload.workflow_run.head_sha} != PR head ${livePr.head.sha}`);
|
|
core.setOutput('skip', 'true');
|
|
return;
|
|
}
|
|
|
|
core.setOutput('skip', 'false');
|
|
core.setOutput('number', String(pr.number));
|
|
core.setOutput('base', livePr.base.ref);
|
|
core.setOutput('head-sha', livePr.head.sha);
|
|
|
|
- name: Find size workflow run for this commit
|
|
if: steps.pr-meta.outputs.skip != 'true'
|
|
id: find-size
|
|
uses: actions/github-script@v8
|
|
with:
|
|
script: |
|
|
const headSha = '${{ steps.pr-meta.outputs.head-sha }}';
|
|
const { data: runs } = await github.rest.actions.listWorkflowRuns({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
workflow_id: 'ci-size-data.yaml',
|
|
head_sha: headSha,
|
|
per_page: 1,
|
|
});
|
|
|
|
const run = runs.workflow_runs[0];
|
|
if (!run) {
|
|
core.setOutput('status', 'pending');
|
|
return;
|
|
}
|
|
|
|
if (run.status !== 'completed') {
|
|
core.setOutput('status', 'pending');
|
|
return;
|
|
}
|
|
|
|
if (run.conclusion !== 'success') {
|
|
core.setOutput('status', 'failed');
|
|
return;
|
|
}
|
|
|
|
core.setOutput('status', 'ready');
|
|
core.setOutput('run-id', String(run.id));
|
|
|
|
- name: Find perf workflow run for this commit
|
|
if: steps.pr-meta.outputs.skip != 'true'
|
|
id: find-perf
|
|
uses: actions/github-script@v8
|
|
with:
|
|
script: |
|
|
const headSha = '${{ steps.pr-meta.outputs.head-sha }}';
|
|
const { data: runs } = await github.rest.actions.listWorkflowRuns({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
workflow_id: 'ci-perf-report.yaml',
|
|
head_sha: headSha,
|
|
per_page: 1,
|
|
});
|
|
|
|
const run = runs.workflow_runs[0];
|
|
if (!run) {
|
|
core.setOutput('status', 'pending');
|
|
return;
|
|
}
|
|
|
|
if (run.status !== 'completed') {
|
|
core.setOutput('status', 'pending');
|
|
return;
|
|
}
|
|
|
|
if (run.conclusion !== 'success') {
|
|
core.setOutput('status', 'failed');
|
|
return;
|
|
}
|
|
|
|
core.setOutput('status', 'ready');
|
|
core.setOutput('run-id', String(run.id));
|
|
|
|
- name: Download size data (current)
|
|
if: steps.pr-meta.outputs.skip != 'true' && steps.find-size.outputs.status == 'ready'
|
|
uses: dawidd6/action-download-artifact@0bd50d53a6d7fb5cb921e607957e9cc12b4ce392 # v12
|
|
with:
|
|
name: size-data
|
|
run_id: ${{ steps.find-size.outputs.run-id }}
|
|
path: temp/size
|
|
|
|
- name: Download size baseline
|
|
if: steps.pr-meta.outputs.skip != 'true' && steps.find-size.outputs.status == 'ready'
|
|
uses: dawidd6/action-download-artifact@0bd50d53a6d7fb5cb921e607957e9cc12b4ce392 # v12
|
|
with:
|
|
branch: ${{ steps.pr-meta.outputs.base }}
|
|
workflow: ci-size-data.yaml
|
|
event: push
|
|
name: size-data
|
|
path: temp/size-prev
|
|
if_no_artifact_found: warn
|
|
|
|
- name: Download perf metrics (current)
|
|
if: steps.pr-meta.outputs.skip != 'true' && steps.find-perf.outputs.status == 'ready'
|
|
uses: dawidd6/action-download-artifact@0bd50d53a6d7fb5cb921e607957e9cc12b4ce392 # v12
|
|
with:
|
|
name: perf-metrics
|
|
run_id: ${{ steps.find-perf.outputs.run-id }}
|
|
path: test-results/
|
|
|
|
- name: Download perf baseline
|
|
if: steps.pr-meta.outputs.skip != 'true' && steps.find-perf.outputs.status == 'ready'
|
|
uses: dawidd6/action-download-artifact@0bd50d53a6d7fb5cb921e607957e9cc12b4ce392 # v12
|
|
with:
|
|
branch: ${{ steps.pr-meta.outputs.base }}
|
|
workflow: ci-perf-report.yaml
|
|
event: push
|
|
name: perf-metrics
|
|
path: temp/perf-baseline/
|
|
if_no_artifact_found: warn
|
|
|
|
- name: Generate unified report
|
|
if: steps.pr-meta.outputs.skip != 'true'
|
|
run: >
|
|
node scripts/unified-report.js
|
|
--size-status=${{ steps.find-size.outputs.status }}
|
|
--perf-status=${{ steps.find-perf.outputs.status }}
|
|
> pr-report.md
|
|
|
|
- name: Remove legacy separate comments
|
|
if: steps.pr-meta.outputs.skip != 'true'
|
|
uses: actions/github-script@v8
|
|
with:
|
|
script: |
|
|
const prNumber = Number('${{ steps.pr-meta.outputs.number }}');
|
|
const legacyMarkers = [
|
|
'<!-- COMFYUI_FRONTEND_SIZE -->',
|
|
'<!-- COMFYUI_FRONTEND_PERF -->',
|
|
];
|
|
|
|
const comments = await github.paginate(github.rest.issues.listComments, {
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: prNumber,
|
|
per_page: 100,
|
|
});
|
|
|
|
for (const comment of comments) {
|
|
if (legacyMarkers.some(m => comment.body?.includes(m))) {
|
|
await github.rest.issues.deleteComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
comment_id: comment.id,
|
|
});
|
|
core.info(`Deleted legacy comment ${comment.id}`);
|
|
}
|
|
}
|
|
|
|
- name: Post PR comment
|
|
if: steps.pr-meta.outputs.skip != 'true'
|
|
uses: ./.github/actions/post-pr-report-comment
|
|
with:
|
|
pr-number: ${{ steps.pr-meta.outputs.number }}
|
|
report-file: ./pr-report.md
|
|
comment-marker: '<!-- COMFYUI_FRONTEND_PR_REPORT -->'
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|