Skip to content

ci(perf): upload trace-only artifact on perf-probe failure - #727

Merged
Astro-Han merged 4 commits into
devfrom
claude/perf-trace-artifact-i698
May 18, 2026
Merged

ci(perf): upload trace-only artifact on perf-probe failure#727
Astro-Han merged 4 commits into
devfrom
claude/perf-trace-artifact-i698

Conversation

@Astro-Han

@Astro-Han Astro-Han commented May 18, 2026

Copy link
Copy Markdown
Owner

Summary

When perf-probe-baseline fails the comparator twice, upload a separate small artifact perf-probe-trace-{attempt} containing only Playwright trace.zip files from the diagnostic re-run, and re-run only the scenarios that actually regressed for trace capture. The on-failure pointer is gated on at least one scenario actually failing.

The existing perf-probe-baseline-{attempt} bundle is unchanged for callers who want the full report.

Why

Closes #698.

The original scope (just upload + pointer) is necessary but not sufficient. Investigation found two structural problems on the fail path:

  1. The trace files were already inside the existing perf-probe-baseline artifact (it bundles e2e/test-results/**), but that bundle is ~90 MB because it also carries the HTML report, videos, and merged perf JSON for both base and head. Measured sustained download from China is about 40 KB/s — the same via mihomo or direct to productionresultssa17.blob.core.windows.net — which puts the full bundle at ~40 minutes per regression. The trace files are effectively unreachable.

  2. The fail path runs the perf spec 12 times (baseline ×4 + confirm ×4 + diagnostic trace ×4). Measured per-step durations on a forced-fail run put the total at ~34 min against the 30-min job ceiling. Any real perf regression risks being cut off before the trace step's artifact is uploaded, leaving the trace artifact from (1) just as unreachable in practice.

This PR addresses both:

  • Splits the trace files into their own small artifact and adds a step-summary + ::notice pointing at it.
  • Filters the four diagnostic trace re-runs to only the scenarios that actually regressed (read from perf-compare-confirm.json). Worst-case fail path drops to ~22-26 min, leaving headroom for setup and future scenario growth.

Related Issue

Closes #698

Human Review Status

Pending.

Review Focus

  • Filter wiring: PAWWORK_PERF_SCENARIOS env in profiles.ts is now AND-ed with the existing profile gate; absent/empty env means "no extra filter", which preserves current behavior.
  • Resolve step output contract: list-failing-scenarios.ts writes default=... and low_end=... directly to $GITHUB_OUTPUT and tolerates malformed input via try/catch + ::warning:: (so a parse failure cannot silently corrupt step outputs that downstream conditions depend on).
  • Upload + pointer gating: both run with always() && ...both compares failed... && at least one profile has failing scenarios. The always() keeps partial traces uploadable if a capture step crashed mid-way; the scenario-non-empty check prevents the pointer from advertising an empty artifact when the comparator failed only with top-level missing_*.
  • Trace step gating: each Capture step ANDs its profile's output with the existing compare-failed and low-end-scope gates, so when only one profile regresses the other profile's two capture steps skip entirely.

Risk Notes

  • Pure CI workflow change plus one perf-only test helper; no app runtime behavior change.
  • New steps only execute when the comparator already failed twice. Green PRs are unaffected (verified by run 26022913394 on this PR, which exercised the new yaml structure end-to-end with no regression and skipped every conditional step).
  • The Capture step if-no-files-found: warn is kept (consistent with the surrounding workflow); trace-step crashes still surface via the step's own exit code.

How To Verify

Local meta-tests + unit tests:
  bun --cwd packages/app test e2e/perf/profiles.unit.ts src/testing/perf-workflow.test.ts  -> 1177 pass / 0 fail
  bun --cwd packages/opencode test test/github/                                              -> 30 pass / 0 fail
YAML parse:
  python3 -c "import yaml; yaml.safe_load(open(...))"                                       -> ok
Fixture exercise of list-failing-scenarios.ts:
  scenarios array with one default + one low-end failure   -> default=homepage-cold, low_end=concurrent-shimmer-extreme
  top-level missing_* with empty scenarios                  -> default=, low_end=
  malformed JSON                                            -> ::warning::, default=, low_end= (no throw)
Manual download bench (existing 90 MB artifact, 30s ceiling):
  via mihomo:        35 KB/s
  --noproxy direct:  39 KB/s
End-to-end CI runs on this branch:
  Green baseline (yaml structure intact, all new gates evaluated skip):  run 26022913394 (this commit)
  Trace capture proven (full diagnostic trace files generated at the expected glob path before timeout):  run 26019182630
Why no full end-to-end fail-path demo: a synthetic long task large enough to trigger every scenario reverts the fail path back to ~34 min (same root cause this PR addresses); a synthetic long task scoped to one route was tested in HomeRedirectRoute on run 26021790694 but did not trigger because perf scenarios navigate directly to /{dir}/session, bypassing that component. The upload + pointer step uses the same actions/upload-artifact@v7 with a path glob that is a strict subset of the existing `Upload perf probe artifacts` step's path (which is proven by the run 26019182630 ✓).

Crosscheck

Multi-model review (Claude opus + Codex high) flagged 13 findings; this PR applies the agreed P1/P2 fixes and rejects the P3 / hypothetical ones:

Applied:
  P1: Gate upload + pointer on per-scenario failures non-empty (covers missing_* and script crash paths).
  P2: Add list-failing-scenarios.ts to paths filter.
  P2: always() guard on upload + pointer so partial trace runs still produce artifact.
  P2: Script writes directly to $GITHUB_OUTPUT via process.env, not stdout redirect.
Rejected:
  P1 contamination from on-first-retry: perf spec does not assert, so it does not retry, so trace files are not produced outside the diagnostic step. Possible but rare; not blocking ship.
  P3 perf/typo/env capture concerns: hypothetical only.
  P3 duplicated trace.zip in big bundle: acceptable (big bundle is "give me everything").
  P3 condition repetition across 4 capture steps: real but not worth abstraction at this size.

Screenshots or Recordings

N/A — CI workflow change only.

Checklist

  • Human review status is stated above as pending, approved, or not required
  • I linked the related issue, or stated why there is no issue
  • This PR has exactly one type label (bug, enhancement, task, or documentation), at least one primary routing label (app, ui, platform, harness, or ci), and exactly one priority label (P0 to P3), or I requested maintainer labeling
  • I described the review focus and any meaningful risks
  • I listed the relevant verification steps and the key result for each
  • I did not introduce unrelated refactors, dependencies, generated files, or file changes beyond the stated scope
  • I manually checked visible UI or copy changes when needed, with screenshots or recordings
  • I considered macOS and Windows impact for platform, packaging, updater, signing, paths, shell, or permissions changes
  • I called out docs, release notes, dependencies, permissions, credentials, deletion behavior, generated content, or local file changes when relevant
  • I reviewed the final diff for unrelated changes and suspicious dependency changes
  • I am targeting dev, and my PR title and commit messages use Conventional Commits in English

Add perf-probe-trace-{attempt} artifact containing only Playwright trace.zip
files from the diagnostic re-run, plus a step summary and ::notice pointing
PR authors at it. The existing perf-probe-baseline artifact is unchanged.

The 90 MB perf-probe-baseline bundle is impractical to download from China
(~40 KB/s sustained, both via mihomo and direct to Azure blob), so authors
cannot inspect traces when a regression fires. A trace-only split brings the
typical download to a few minutes and gives the on-failure pointer a single
named target.

Refs #698
@gemini-code-assist

Copy link
Copy Markdown

Note

Gemini is unable to generate a review for this pull request due to the file types involved not being currently supported.

@Astro-Han Astro-Han added the task Narrow execution, audit, spike, migration, tracking, or upstream follow-up work label May 18, 2026
@github-actions github-actions Bot added the ci Continuous integration / GitHub Actions label May 18, 2026
@coderabbitai

coderabbitai Bot commented May 18, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@Astro-Han has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 3 minutes before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 3f660817-abd6-45e4-96e8-7a4ed20346d9

📥 Commits

Reviewing files that changed from the base of the PR and between cc91973 and 0565502.

📒 Files selected for processing (2)
  • .github/workflows/perf-probe-baseline.yml
  • packages/app/script/list-failing-scenarios.ts
📝 Walkthrough

Walkthrough

Adds an env-driven perf scenario filter, a CLI to list failing scenarios, and CI changes that gate trace captures on failing scenarios and upload Playwright trace artifacts with run-summary instructions when perf comparisons fail.

Changes

Perf probe trace artifact capture and documentation

Layer / File(s) Summary
Env-driven scenario filter and tests
packages/app/e2e/perf/profiles.ts, packages/app/e2e/perf/profiles.unit.ts
Parses PAWWORK_PERF_SCENARIOS into a Set and makes shouldRunScenario honor that filter; adds unit tests covering env lifecycle and edge cases.
CLI to enumerate failing scenarios
packages/app/script/list-failing-scenarios.ts
New script reads a perf-compare.json, emits failing scenario names grouped by profile (low-end -> low_end) as profile=name1,name2,... for workflow consumption.
Workflow trace capture gating and artifact upload
.github/workflows/perf-probe-baseline.yml
Adds a step to list failing scenarios and uses its outputs to gate base/head and low-end trace captures (setting PAWWORK_PERF_SCENARIOS), uploads trace.zip files from base/head test-results as perf-probe-trace-${{ github.run_attempt }} (7-day retention, warn if none), and writes a step summary with npx playwright show-trace instructions.

Sequence Diagram(s)

sequenceDiagram
  participant GitHub_Actions
  participant list_fail_script
  participant TraceCaptureJob
  participant ArtifactStore
  GitHub_Actions->>list_fail_script: run list-failing-scenarios on perf-compare.json
  list_fail_script-->>GitHub_Actions: outputs default=<csv>, low_end=<csv>
  GitHub_Actions->>TraceCaptureJob: conditionally run trace captures (set PAWWORK_PERF_SCENARIOS)
  TraceCaptureJob->>ArtifactStore: upload trace.zip from base/head dirs
  ArtifactStore-->>GitHub_Actions: artifact URL
  GitHub_Actions->>GitHub_Actions: append Perf trace artifact to $GITHUB_STEP_SUMMARY
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • Astro-Han/pawwork#635: Modifies packages/app/e2e/perf/profiles.ts scenario gating; interacts with the new env-filter behavior.
  • Astro-Han/pawwork#607: Introduced/modified the perf-probe-baseline workflow that this PR extends.
  • Astro-Han/pawwork#609: Related workflow changes for diagnostic trace handling and collection.

Suggested labels

app, harness

Poem

🐰 I parsed the list and scoped the run,
Filters set, the traces spun,
CI gathers ZIPs both old and new,
A bunny hops to show the view,
npx plays the trace for you.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title "ci(perf): upload trace-only artifact on perf-probe failure" clearly and specifically describes the main change—uploading a separate trace artifact on perf-probe failure.
Linked Issues check ✅ Passed The PR meets the coding requirements of issue #698: updates perf-probe-baseline.yml to upload trace artifacts, adds pointer in step output, filters scenarios via PAWWORK_PERF_SCENARIOS, and provides verification approach.
Out of Scope Changes check ✅ Passed All changes are scoped to issue #698 objectives: workflow updates for trace artifact upload, scenario filtering, and supporting tooling; no unrelated refactors, dependency changes, or scope creep detected.
Description check ✅ Passed The pull request description is comprehensive and well-structured, covering all required template sections including Summary, Why, Related Issue, Human Review Status, Review Focus, Risk Notes, How To Verify, and Checklist.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/perf-trace-artifact-i698

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Astro-Han Astro-Han added the P2 Medium priority label May 18, 2026
@github-actions github-actions Bot added the P3 Low priority label May 18, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested priority: P3 (only low-risk paths changed (.github/workflows/perf-probe-baseline.yml)).

P1/P0 are reserved for maintainer confirmation. Please relabel manually if this is a release blocker, security issue, data-loss risk, or updater/runtime failure.

@Astro-Han Astro-Han added tech-debt Supplemental cleanup, maintainability, architecture, test, or quality debt context and removed P3 Low priority labels May 18, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
.github/workflows/perf-probe-baseline.yml (1)

334-334: Consider updating to actions/upload-artifact@v7.0.1.

The SHA 043fb46d1a93c77aae656e7c1c64a875d1fc6a0a correctly matches the v7 tag. A newer patch version (v7.0.1) is available, released on 2026-04-10. If you want to stay current with the latest patch, update the action to the v7.0.1 release.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/perf-probe-baseline.yml at line 334, Update the GitHub
Actions step that references actions/upload-artifact by replacing the pinned SHA
"actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a" with the
newer patch tag "actions/upload-artifact@v7.0.1" (the step using the
actions/upload-artifact reference should be updated to use `@v7.0.1` instead of
the SHA).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In @.github/workflows/perf-probe-baseline.yml:
- Line 334: Update the GitHub Actions step that references
actions/upload-artifact by replacing the pinned SHA
"actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a" with the
newer patch tag "actions/upload-artifact@v7.0.1" (the step using the
actions/upload-artifact reference should be updated to use `@v7.0.1` instead of
the SHA).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 92f44a6b-0328-4c04-8ec5-01ee959e6adf

📥 Commits

Reviewing files that changed from the base of the PR and between 0e64c23 and d4b34c5.

📒 Files selected for processing (1)
  • .github/workflows/perf-probe-baseline.yml

@github-actions

github-actions Bot commented May 18, 2026

Copy link
Copy Markdown

Perf delta summary

Comparator: pass

Profile / Scenario interaction median interaction worst long task max tbt frame gap p95 frame gap max jank count cls status
default / homepage-cold 32 -> 40 (+8) 64 -> 64 (0) 91 -> 69 (-22) 41 -> 19 (-22) 16.8 -> 33.3 (+16.5) 150 -> 116.7 (-33.3) 4 -> 4 (0) 0 -> 0 (0) pass
default / long-session-input-lag 48 -> 48 (0) 48 -> 48 (0) 0 -> 0 (0) 0 -> 0 (0) 16.7 -> 16.7 (0) 16.8 -> 16.8 (0) 0 -> 0 (0) 0 -> 0 (0) pass
default / session-streaming-long 40 -> 48 (+8) 80 -> 56 (-24) 0 -> 0 (0) 0 -> 0 (0) 33.3 -> 16.8 (-16.5) 33.4 -> 33.3 (-0.1) 0 -> 0 (0) 0 -> 0 (0) pass
default / tool-call-expand 16 -> 16 (0) 16 -> 40 (+24) 0 -> 0 (0) 0 -> 0 (0) 16.7 -> 16.7 (0) 16.7 -> 16.7 (0) 0 -> 0 (0) 0 -> 0 (0) pass
default / tool-default-open-heavy-bash 24 -> 24 (0) 24 -> 32 (+8) 61 -> 61 (0) 11 -> 12 (+1) 33.4 -> 49.9 (+16.5) 150 -> 166.6 (+16.6) 1 -> 2 (+1) 0 -> 0 (0) pass
default / terminal-side-panel-open 48 -> 48 (0) 48 -> 56 (+8) 0 -> 0 (0) 0 -> 0 (0) 33.3 -> 33.4 (+0.1) 33.3 -> 33.4 (+0.1) 0 -> 0 (0) 0 -> 0 (0) pass
default / session-scroll-reading 32 -> 24 (-8) 40 -> 24 (-16) 0 -> 0 (0) 0 -> 0 (0) 16.8 -> 16.8 (0) 16.8 -> 16.8 (0) 0 -> 0 (0) 0.505 -> 0.505 (0) warn: cls
low-end / session-scroll-reading-long 48 -> 56 (+8) 64 -> 72 (+8) 61 -> 118 (+57) 21 -> 116 (+95) 16.8 -> 16.8 (0) 66.7 -> 150 (+83.3) 1 -> 3 (+2) 0.011 -> 0.011 (0) pass
low-end / session-timeline-recompute 120 -> 120 (0) 144 -> 128 (-16) 104 -> 109 (+5) 192 -> 169 (-23) 100 -> 83.4 (-16.6) 166.7 -> 183.4 (+16.7) 4 -> 3 (-1) 0.081 -> 0.081 (0) pass
low-end / concurrent-shimmer-extreme 0 -> 0 (0) 0 -> 0 (0) 0 -> 0 (0) 0 -> 0 (0) 16.7 -> 16.7 (0) 16.8 -> 16.8 (0) 0 -> 0 (0) 0 -> 0 (0) pass

@github-actions github-actions Bot added app Application behavior and product flows ui Design system and user interface labels May 18, 2026
@Astro-Han
Astro-Han force-pushed the claude/perf-trace-artifact-i698 branch from 1511c50 to d4b34c5 Compare May 18, 2026 08:01
@github-actions github-actions Bot removed app Application behavior and product flows ui Design system and user interface labels May 18, 2026
Add a PAWWORK_PERF_SCENARIOS env filter on top of the existing profile gate
in shouldRunScenario, and resolve the failing scenario list from
perf-compare-confirm.json before the diagnostic trace steps. Each of the
four Capture trace steps now passes only its profile's failing scenarios to
the spec, and skips entirely when that profile has no failure.

Today the four trace steps re-run the full perf spec (all scenarios in the
profile), even when a regression touched only one scenario. Measured on a
forced-fail run, baseline + confirm + trace together cost ~34 min on the
30-min job ceiling, so any real perf regression risks being cut off before
the trace artifact is produced. Filtering trace to the failing scenarios
brings the worst-case fail path to ~22-26 min, leaving headroom for setup
and future scenario growth.

Confirm steps still run the whole profile to preserve the workflow's
false-positive guard: a scenario must fail twice across two independent
runs before its trace is recorded.

Refs #698
@github-actions github-actions Bot added app Application behavior and product flows ui Design system and user interface labels May 18, 2026
@Astro-Han
Astro-Han force-pushed the claude/perf-trace-artifact-i698 branch from 3060d1c to cc91973 Compare May 18, 2026 08:37
@github-actions github-actions Bot removed the ui Design system and user interface label May 18, 2026
Astro-Han added 2 commits May 18, 2026 16:42
Address crosscheck findings on the perf trace artifact pipeline:

- Gate Upload perf trace artifact and Print perf trace artifact pointer on
  steps.failing_scenarios.outputs being non-empty, so a top-level missing_*
  comparator failure (or any other path where no per-scenario regression is
  detected) no longer prints a pointer to an empty artifact.
- Wrap both gates with always() so a trace capture step that exits non-zero
  partway still uploads whatever trace.zip files were produced before the
  failure, instead of being skipped by the default cancel-on-prior-failure
  behavior.
- Have list-failing-scenarios.ts try/catch the JSON parse and write directly
  to process.env.GITHUB_OUTPUT instead of relying on shell stdout
  redirection, so stray script output or a malformed input cannot silently
  corrupt the step outputs that downstream conditions depend on. A
  ::warning:: surfaces the parse failure for the run author.
- Add packages/app/script/list-failing-scenarios.ts to the workflow paths
  filter so future edits to the selector script actually trigger this
  workflow.

Refs #698
…hanges

Add packages/app/script/list-failing-scenarios.ts to is_low_end_path() so a
PR that touches only this selector script still exercises the low_end output
contract that the script writes, mirroring how compare-perf.ts and
merge-perf-artifacts.ts already gate the low-end profile.

Refs #698
@Astro-Han
Astro-Han merged commit 2ddedf9 into dev May 18, 2026
28 checks passed
@Astro-Han
Astro-Han deleted the claude/perf-trace-artifact-i698 branch May 18, 2026 09:15
Astro-Han added a commit that referenced this pull request May 18, 2026
Astro-Han added a commit that referenced this pull request May 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app Application behavior and product flows ci Continuous integration / GitHub Actions P2 Medium priority task Narrow execution, audit, spike, migration, tracking, or upstream follow-up work tech-debt Supplemental cleanup, maintainability, architecture, test, or quality debt context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Task] perf: upload Playwright trace artifact on perf-probe-baseline failure

1 participant