ci: route all Codecov flags through the deferred workflow_run upload#6730
Conversation
…R comments Fork PRs never receive secrets.CODECOV_TOKEN on the pull_request event, so the direct codecov-action step falls back to Codecov's tokenless path. That path is rate-limited: under a burst of fork-PR uploads Codecov processes the report but silently drops the PR comment (reported on apache#6685). Stage the frontend lcov + JUnit reports as an artifact in build.yml and upload them with a token from a new workflow_run-triggered codecov-upload.yml, which runs in the base-repo context where the token is available. Authenticated uploads are not rate-limited, so the comment posts reliably even in bursts. Scope: frontend flag only (proof of concept). Other flags still upload directly.
Automated Reviewer SuggestionsBased on the
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #6730 +/- ##
============================================
+ Coverage 74.65% 74.83% +0.17%
- Complexity 3438 3448 +10
============================================
Files 1160 1160
Lines 45793 45793
Branches 5069 5069
============================================
+ Hits 34189 34267 +78
+ Misses 9953 9878 -75
+ Partials 1651 1648 -3
*This pull request uses carry forward flags. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR reroutes frontend Codecov uploads away from the pull_request build (which cannot access CODECOV_TOKEN on fork PRs) to a follow-up workflow_run workflow that runs in the base-repo context, enabling authenticated uploads and more reliable Codecov PR comments for fork PRs.
Changes:
- Add a new
codecov-upload.ymlworkflow that runs onworkflow_run(after “Required Checks”) to download a staged artifact and upload coverage + test results to Codecov usingCODECOV_TOKEN. - Remove the direct frontend Codecov upload steps from
build.ymland instead stagelcov.info+ JUnit XML + PR/sha/branch metadata into acodecov-frontendartifact.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| .github/workflows/codecov-upload.yml | New workflow that downloads the staged frontend Codecov artifact from the source run and re-uploads it with an authenticated token. |
| .github/workflows/build.yml | Replaces direct frontend Codecov uploads with artifact staging + upload for deferred processing by codecov-upload.yml. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
| config | throughput | MB/s | latency | max Δ latest / 7d | |
|---|---|---|---|---|---|
| 🔴 | bs=10 sw=10 sl=64 | 398 | 0.243 | 23,506/32,853/32,853 us | 🔴 -11.2% / 🔴 +103.8% |
| ⚪ | bs=100 sw=10 sl=64 | 941 | 0.574 | 104,267/130,142/130,142 us | ⚪ within ±5% / 🔴 +21.2% |
| ⚪ | bs=1000 sw=10 sl=64 | 1,083 | 0.661 | 926,271/993,907/993,907 us | ⚪ within ±5% / 🟢 +5.9% |
Baseline details
Latest main ef55ad8 from same runner
| config | metric | PR | latest main | 7d avg | Δ latest | Δ 7d |
|---|---|---|---|---|---|---|
| bs=10 sw=10 sl=64 | throughput | 398 tuples/sec | 448 tuples/sec | 760.2 tuples/sec | -11.2% | -47.6% |
| bs=10 sw=10 sl=64 | MB/s | 0.243 MB/s | 0.273 MB/s | 0.464 MB/s | -11.0% | -47.6% |
| bs=10 sw=10 sl=64 | p50 | 23,506 us | 22,563 us | 12,781 us | +4.2% | +83.9% |
| bs=10 sw=10 sl=64 | p95 | 32,853 us | 32,034 us | 16,118 us | +2.6% | +103.8% |
| bs=10 sw=10 sl=64 | p99 | 32,853 us | 32,034 us | 19,074 us | +2.6% | +72.2% |
| bs=100 sw=10 sl=64 | throughput | 941 tuples/sec | 963 tuples/sec | 988.68 tuples/sec | -2.3% | -4.8% |
| bs=100 sw=10 sl=64 | MB/s | 0.574 MB/s | 0.588 MB/s | 0.603 MB/s | -2.4% | -4.9% |
| bs=100 sw=10 sl=64 | p50 | 104,267 us | 100,066 us | 101,448 us | +4.2% | +2.8% |
| bs=100 sw=10 sl=64 | p95 | 130,142 us | 128,180 us | 107,410 us | +1.5% | +21.2% |
| bs=100 sw=10 sl=64 | p99 | 130,142 us | 128,180 us | 120,258 us | +1.5% | +8.2% |
| bs=1000 sw=10 sl=64 | throughput | 1,083 tuples/sec | 1,088 tuples/sec | 1,023 tuples/sec | -0.5% | +5.9% |
| bs=1000 sw=10 sl=64 | MB/s | 0.661 MB/s | 0.664 MB/s | 0.624 MB/s | -0.5% | +5.9% |
| bs=1000 sw=10 sl=64 | p50 | 926,271 us | 924,740 us | 983,888 us | +0.2% | -5.9% |
| bs=1000 sw=10 sl=64 | p95 | 993,907 us | 967,303 us | 1,030,100 us | +2.8% | -3.5% |
| bs=1000 sw=10 sl=64 | p99 | 993,907 us | 967,303 us | 1,056,513 us | +2.8% | -5.9% |
Raw CSV
config_idx,batch_size,schema_width,string_len,num_batches,total_ms,total_tuples,total_bytes,tuples_per_sec,mb_per_sec,lat_p50_us,lat_p95_us,lat_p99_us
0,10,10,64,20,502.93,200,128000,398,0.243,23505.91,32853.07,32853.07
1,100,10,64,20,2126.08,2000,1280000,941,0.574,104266.89,130141.51,130141.51
2,1000,10,64,20,18460.04,20000,12800000,1083,0.661,926270.65,993906.98,993906.98…v upload Clarify why the staging/upload-artifact steps use !cancelled() rather than always(): the status-check function overrides the implicit success(), so staging still runs when tests fail (matching the prior always()/!cancelled() upload steps) and only skips cancelled runs. No behavior change.
|
Looked into all five Copilot findings — they're non-issues; details below. Pushed one comment-only commit (48efa63) to spell out the first point.
Empty k_arg() { if [ -n "$(eval echo \$"CC_$1")" ]; then echo "--$(lower "$1")"; fi }
v_arg() { if [ -n "$(eval echo \$"CC_$1")" ]; then echo "$(eval echo \$"CC_$1")"; fi }
...
CC_ARGS+=( $(k_arg PR) $(v_arg PR))
CC_ARGS+=( $(k_arg SHA) $(v_arg SHA))
CC_ARGS+=( $(k_arg BRANCH) $(v_arg BRANCH))So on a push to main |
|
Thank for the fix, but why only frontend has this issue? should we defer all coverage report uploading to the same job? also can batching them together reduce the usage on the allowence? |
|
Good questions. Why only frontend? Not frontend-specific — any flag on a fork PR can hit it. Frontend just surfaced it: the campaign opens ~10 frontend fork PRs within minutes, and each fires 3 tokenless uploads (coverage + unit + browser junit) vs 1–2 for other flags, so it trips Codecov's tokenless rate limit fastest. Defer all flags? Right direction — I scoped the PoC to frontend for a reviewable diff. Not a pure copy-paste, though: amber's coverage is a same-basename glob across ~8 modules (flat-copy would drop 7/8), amber-integration is results-only and uploads from both the ubuntu+macOS legs, and every flag needs the Batching to save allowance? Not really — no per-upload quota is in play; the pressure is the tokenless rate limit. Per-module reports can't collapse into fewer uploads without cross-tagging, and the artifact hand-off adds a little Actions work. Authentication (the token), not batching, is the fix. |
Generalize the frontend proof of concept to every flag so fork PRs get an authenticated (non-rate-limited) upload and a reliable Codecov comment across the board, not just for frontend. - build.yml: each coverage job now stages its reports as a codecov-<flag> artifact via .github/scripts/stage-codecov.sh instead of uploading inline (amber, amber-integration, platform x6, pyamber, agent-service; frontend moved to the same uniform layout). The script preserves the directory tree so amber's ~8 same-basename module jacoco.xml don't collide. Staging is guarded off backport builds (artifact-name collisions across the target matrix) and, for the dual-OS/multi-leg jobs, pinned to the single leg that produces the reports. - codecov-upload.yml: a per-flag matrix downloads each artifact and re-uploads it with the token, using directory: scoping so Codecov's search finds every file per flag. Coverage uploads fail hard (fail_ci_if_error: true); a new notify-failure job then comments on the PR with a link + the run_id to manually dispatch, since Codecov only self-comments on success. Test-results stay best-effort. Codecov requires one upload per flag (flags apply to all files in an upload and carryforward needs the flag at upload time), so the calls can't be batched into fewer uploads without dropping the per-flag/carryforward model; the token, not batching, is what removes the tokenless rate-limit pressure.
|
Done — pushed. Three things: Failure notification (your main concern). Added a All flags in one PR. Every flag now stages a Batching to cut Codecov calls. We can't, not without dropping the per-flag model: Codecov requires one upload per flag (flags in a single upload apply to all its files, and carryforward — which our One thing I'll confirm on the first live run after merge: the test-results (Test Analytics) upload is best-effort, so I want to eyeball that each flag's JUnit files are found — but that's separate from the coverage report. |
Per review on apache#6730: - test-results upload now also uses fail_ci_if_error: true, so a Test Analytics upload error trips notify-failure instead of being silently dropped. - Drop the "if Codecov's comment appears, ignore this" line from the failure comment: on a re-run a stale Codecov success comment from a prior run can coexist with a fresh failure, which made that note misleading.
The license-eye header check (Check License Headers) failed because the new staging script was missing the Apache license header.
…he#6824) ### What changes were proposed in this PR? Follow-up to apache#6730. The deferred `Codecov Upload` workflow hardcoded all 11 flags in its matrix and tried to download each from the source run. On a label-gated PR — e.g. a frontend-only PR that only stages `codecov-frontend` — the other 10 legs hit `##[error] Artifact not found for name: codecov-<flag>`, which looks like a name mismatch; and because the download used `continue-on-error: true`, a genuinely failed download was swallowed, the leg went green, and `notify-failure` never fired. **Fix:** add a `discover` job that lists the source run's *actual* `codecov-*` artifacts and drives the upload matrix from that (`fromJSON`), and drop `continue-on-error` on the download. - **No more spurious errors** — only the flags the source run actually built are processed; a frontend-only PR runs one clean leg. - **Failures surface** — a listed artifact that then fails to download or upload fails the leg, so `notify-failure` fires (previously it went silently green). - Also removes the hardcoded flag list, so adding a `platform` service no longer needs a matching matrix row here. Observed on the first live run after apache#6730 merged ([run 29984668372](https://github.com/apache/texera/actions/runs/29984668372), triggered by a frontend-only PR's checks): `frontend` uploaded fine, but 10 legs logged `Artifact not found` for the label-gated flags and the run still went green. ### Any related issues, documentation, discussions? Follow-up to apache#6730 (reported on apache#6685). ### How was this PR tested? - `workflow_run` only activates from the copy of the file on the default branch, so this can't run on its own PR. Validated by YAML lint and an adversarial review of the discover → upload → notify flow: empty-flags cleanly skips (no failure, no notify), the dynamic `fromJSON` matrix handles one or many flags, a download/upload failure now fails the leg and fires `notify-failure`, `amber-integration` (results-only) skips the coverage step via `hashFiles`, and the `workflow_dispatch` path resolves the run id. - The `workflow_dispatch` (`run_id`) entry remains for manual post-merge validation against a finished *Required Checks* run. ### Was this PR authored or co-authored using generative AI tooling? Yes. Generated-by: Claude Code (Opus 4.8 [1M context])
What changes were proposed in this PR?
Route every Codecov flag's upload through a follow-up
workflow_runworkflow instead of uploading inline from thepull_requestbuild, so fork PRs get authenticated (non-rate-limited) uploads and a reliable Codecov PR comment.Problem. A PR from a fork never receives
secrets.CODECOV_TOKEN(the build runs onpull_request, and GitHub withholds secrets from fork runs). The inlinecodecov-actionsteps therefore fall back to Codecov's tokenless path, which is rate-limited; under a burst of fork-PR uploads Codecov still processes the report but silently drops the PR comment (reported on #6685).Fix.
build.yml: each coverage job stages its reports as acodecov-<flag>artifact via.github/scripts/stage-codecov.sh(coverage/+results/+ pr/sha/branch identifiers) instead of uploading inline. The script preserves the directory tree so amber's ~8 same-basename modulejacoco.xmldon't collide. Staging is skipped on backport builds (artifact-name collisions across the target matrix) and pinned to the single producing leg for the dual-OS / multi-python jobs.codecov-upload.yml: a per-flag matrix runs onworkflow_runafter Required Checks, in the base-repo context whereCODECOV_TOKENis available. It downloads each artifact and re-uploads with the token, usingdirectory:scoping so Codecov's search finds every file per flag.notify-failurejob then comments on the PR (a link to the failed run + therun_idto manually dispatch) — Codecov only self-comments on success, so this covers the failure case. A delayed / no-runner run posts nothing at all, which is itself the signal that the upload is stuck.Flags covered: frontend, amber, amber-integration (test-results only), pyamber, agent-service, and the 6 platform services.
Why not batch into fewer calls: Codecov requires one upload per flag (flags in a single upload apply to all its files, and carryforward — which
codecov.ymlrelies on — needs the flag set at upload time), with no path-based auto-assignment, so the calls can't be collapsed without dropping the per-flag / carryforward model. The token — not batching — is what removes the tokenless rate-limit pressure.Any related issues, documentation, discussions?
Reported on #6685.
How was this PR tested?
workflow_runonly triggers from the copy of the file on the default branch, socodecov-upload.ymlactivates only after merge; it exposes aworkflow_dispatch(run_id) entry to validate against a finished Required Checks run immediately after merge..github/scripts/stage-codecov.shwas exercised locally: multi-module glob → no basename collisions, single-file flags, and the empty-PR (push) case.codecov-<flag>artifacts can be inspected on this run.matrix.coveragegating).directory:— best-effort, and separate from the coverage report.Since the deferred workflow can only activate on
main, if anything is off the whole change reverts as a single PR.Was this PR authored or co-authored using generative AI tooling?
Yes.
Generated-by: Claude Code (Opus 4.8 [1M context])