fix(ci): poll for E2E completion in release gate#252
Conversation
…mmediately The release-please PR opens before E2E tests finish on main, causing the release gate to fail with "no run found". Now polls every 30s (up to 15 min) for the E2E run to complete before checking the result. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: b1058120b65d
WalkthroughAdds a release-gate job that detects desktop-related changes since the last non-staging tag and replaces one-shot E2E checks with polling logic for Web and Desktop E2E runs; gates Desktop E2E on detected desktop changes and accepts a recent successful run if no HEAD run exists. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor ReleaseGate as Release Gate Workflow
participant GitHubAPI as GitHub API
participant WebE2E as Web E2E (main)
participant DesktopE2E as Desktop E2E (HEAD / recent)
Note over ReleaseGate,GitHubAPI: Detect changes since last non-staging tag
ReleaseGate->>GitHubAPI: get latest non-staging tag (prev_tag)
ReleaseGate->>GitHubAPI: diff prev_tag..HEAD against DESKTOP_PATTERNS
GitHubAPI-->>ReleaseGate: desktop=true/false, prev_tag
alt desktop == false
ReleaseGate->>ReleaseGate: skip Desktop E2E (Summary)
else desktop == true
Note over ReleaseGate,WebE2E: Poll Web E2E run for main
ReleaseGate->>GitHubAPI: query e2e runs on main (repeat until conclusion or timeout)
GitHubAPI-->>ReleaseGate: status/conclusion
alt Web E2E success
Note over ReleaseGate,DesktopE2E: Poll Desktop E2E for HEAD
ReleaseGate->>GitHubAPI: query Desktop E2E runs for HEAD (repeat)
GitHubAPI-->>ReleaseGate: run exists? status/conclusion/sha
alt Desktop HEAD run found and success
ReleaseGate->>ReleaseGate: pass Desktop gate
else no HEAD run
ReleaseGate->>GitHubAPI: list successful Desktop runs in prev_tag..HEAD
GitHubAPI-->>ReleaseGate: successful SHAs
alt recent successful SHA found
ReleaseGate->>ReleaseGate: accept recent success, pass gate
else
ReleaseGate->>ReleaseGate: error (no suitable Desktop E2E)
end
end
else Web E2E failure or timeout
ReleaseGate->>ReleaseGate: error (Web E2E gate failed)
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
.github/workflows/release-gate.yml (1)
55-69: Desktop E2E could face the same race condition.The Desktop E2E check doesn't implement polling. If the Desktop workflow is still running when this check executes,
DESKTOP_CONCLUSIONwill be empty (sinceconclusionis null for in-progress runs), and it will be treated as "no run for this commit (skipped)" rather than waiting for the result.Per the comment "block only if it ran and failed," this appears intentional — Desktop E2E is an optional gate. However, if Desktop E2E is running and later fails, this gate would incorrectly pass.
If Desktop E2E should be a hard gate when it runs, consider adding similar polling logic. If the current "fail-fast only" behavior is intentional, a clarifying comment would help future maintainers.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/release-gate.yml around lines 55 - 69, The Desktop E2E gate reads DESKTOP_CONCLUSION from gh run list and treats an in-progress run (conclusion null) as "skipped", which can miss a later failure; update the block that queries e2e-desktop.yml for MAIN_SHA (variable DESKTOP_CONCLUSION) to implement the same polling/retry logic used elsewhere: loop/retry gh run list until conclusion is non-empty or a timeout/attempts limit is reached, then fail if DESKTOP_CONCLUSION != "success", otherwise report passed; alternatively, if the current fail-only-if-already-finished behavior is intended, add a clarifying comment above the DESKTOP_CONCLUSION logic documenting that in-progress runs are considered “skipped” by design.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In @.github/workflows/release-gate.yml:
- Around line 55-69: The Desktop E2E gate reads DESKTOP_CONCLUSION from gh run
list and treats an in-progress run (conclusion null) as "skipped", which can
miss a later failure; update the block that queries e2e-desktop.yml for MAIN_SHA
(variable DESKTOP_CONCLUSION) to implement the same polling/retry logic used
elsewhere: loop/retry gh run list until conclusion is non-empty or a
timeout/attempts limit is reached, then fail if DESKTOP_CONCLUSION != "success",
otherwise report passed; alternatively, if the current
fail-only-if-already-finished behavior is intended, add a clarifying comment
above the DESKTOP_CONCLUSION logic documenting that in-progress runs are
considered “skipped” by design.
Instead of checking whether the latest main commit has a desktop E2E run, diff changed files between the previous release tag and HEAD against desktop-related path patterns (mirrored from e2e-desktop.yml). Only require desktop E2E to pass when desktop code actually changed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: 0a98db514e8d
- Remove `push` trigger from CI (already ran on PR) - Desktop E2E triggers directly on push to main with change detection instead of chaining off CI via workflow_run - Release gate detects desktop changes across the full release range (last tag..HEAD), not just the HEAD commit - When desktop changes detected, finds any successful desktop E2E run within the release range (not necessarily at HEAD) - If a desktop E2E run exists for HEAD, polls until it completes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: 2b30c684b7fc
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
.github/workflows/release-gate.yml (1)
169-170: Minor: Consider handling API pagination for large commit ranges.The
/compareendpoint returns up to 250 commits by default. If the release range spans more commits, some SHAs may be missing fromRANGE_COMMITS, potentially causing a false negative when searching for a successful Desktop E2E run.For very long release cycles, you may need to paginate or use
git rev-listlocally instead:RANGE_COMMITS=$(git rev-list "${PREV_TAG}..${MAIN_SHA}")This requires the repo to be checked out in this job (currently it's not).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/release-gate.yml around lines 169 - 170, The RANGE_COMMITS assignment uses gh api "repos/.../compare/${PREV_TAG}...${MAIN_SHA}" which can return at most 250 commits and may miss SHAs; update the workflow to handle large ranges by either (A) checking out the repo in this job (add actions/checkout@v3) and replace the gh api call with a local git rev-list "${PREV_TAG}..${MAIN_SHA}" to enumerate all SHAs, or (B) implement proper pagination against the /compare endpoint (looping on gh api with page parameters until no more commits) and aggregate commits into RANGE_COMMITS; ensure you update the variable assignment that references RANGE_COMMITS accordingly and keep the existing logic that searches for the Desktop E2E run unchanged..github/workflows/e2e-desktop.yml (1)
27-43: Consider extracting desktop path patterns to a shared location.The desktop path patterns are duplicated between this file and
release-gate.yml(lines 41-56). If these patterns diverge, the release gate could incorrectly skip or require Desktop E2E verification.One option is to extract the patterns to a reusable composite action or a shared config file that both workflows reference, reducing maintenance burden and preventing drift.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/e2e-desktop.yml around lines 27 - 43, The desktop path pattern list under the "filters: | desktop:" block is duplicated between this workflow and release-gate.yml and should be centralized to avoid drift; extract the path patterns into a single reusable source (either a composite action or a shared YAML/JSON config that exports the array) and update both e2e-desktop.yml and release-gate.yml to reference that single source instead of inline lists; ensure the symbol you change is the "filters: | desktop:" block in both workflows and verify the workflows still expand the same pattern set (and run CI) after switching to the shared reference.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/release-gate.yml:
- Line 78: The workflow's job timeout (timeout-minutes) is too low for the
combined Desktop E2E and Web E2E polling windows; update either the timeout or
the Desktop E2E polling constants so both checks can complete. Specifically,
either increase timeout-minutes from 20 to a value that accommodates Web E2E
plus Desktop E2E polling, or reduce Desktop E2E MAX_ATTEMPTS and/or
POLL_INTERVAL (the variables referenced in the Desktop E2E polling loop) so its
total wait time plus the Web E2E polling fits within the existing timeout;
ensure any change keeps both polling loops' total durations within the job
timeout to avoid premature job termination.
---
Nitpick comments:
In @.github/workflows/e2e-desktop.yml:
- Around line 27-43: The desktop path pattern list under the "filters: |
desktop:" block is duplicated between this workflow and release-gate.yml and
should be centralized to avoid drift; extract the path patterns into a single
reusable source (either a composite action or a shared YAML/JSON config that
exports the array) and update both e2e-desktop.yml and release-gate.yml to
reference that single source instead of inline lists; ensure the symbol you
change is the "filters: | desktop:" block in both workflows and verify the
workflows still expand the same pattern set (and run CI) after switching to the
shared reference.
In @.github/workflows/release-gate.yml:
- Around line 169-170: The RANGE_COMMITS assignment uses gh api
"repos/.../compare/${PREV_TAG}...${MAIN_SHA}" which can return at most 250
commits and may miss SHAs; update the workflow to handle large ranges by either
(A) checking out the repo in this job (add actions/checkout@v3) and replace the
gh api call with a local git rev-list "${PREV_TAG}..${MAIN_SHA}" to enumerate
all SHAs, or (B) implement proper pagination against the /compare endpoint
(looping on gh api with page parameters until no more commits) and aggregate
commits into RANGE_COMMITS; ensure you update the variable assignment that
references RANGE_COMMITS accordingly and keep the existing logic that searches
for the Desktop E2E run unchanged.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
.github/workflows/ci.yml.github/workflows/e2e-desktop.yml.github/workflows/release-gate.yml
Web E2E polls up to 15min + Desktop E2E polls up to 20min = 35min max. The 20min job timeout was too low for both phases to complete. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: 7f3f99d856db
There was a problem hiding this comment.
Pull request overview
This PR updates GitHub Actions workflows to make the release gate more reliable by waiting for the main branch E2E workflows to finish (instead of failing when the run hasn’t appeared yet), and by adjusting when Desktop E2E and CI run.
Changes:
- Add a “detect changes since last release” job and use it to conditionally enforce Desktop E2E in the release gate.
- Poll for Web E2E completion (up to ~15 minutes) before checking conclusions, and add a job timeout safety net.
- Change Desktop E2E to run on
pushtomain(instead ofworkflow_run), and removepush-to-mainCI runs (PR-only CI).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| .github/workflows/release-gate.yml | Adds polling + desktop-change detection to avoid “no run found” race; gates Desktop E2E only when needed. |
| .github/workflows/e2e-desktop.yml | Switches Desktop E2E trigger to push on main, aligning it with release-gate expectations. |
| .github/workflows/ci.yml | Makes CI PR-only and simplifies conditional execution based on the paths-filter outputs. |
- Use `// empty` in jq to prevent null conclusions from breaking poll loops (null is output as "null" string, not empty) - Use `grep -Fq` for fixed-string matching in change detection (dots in patterns like `vite.config.` are regex wildcards) - Find the most recent desktop E2E run in the release range and check its conclusion, rather than accepting any successful run (prevents stale success from masking a later failure) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: f1e3905e60a0
Merge the separate cargo-check-{os} and cargo-test-{os} jobs into
unified cargo-{os} jobs that run check then test sequentially. This
eliminates duplicate runner provisioning, checkout, dependency
installation, and cache restore across 3 platforms — saving several
minutes of CI wall time per run.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 584cc9d7ce70
- Short-circuit with clear error when no previous release tag exists and no Desktop E2E run is available for HEAD - Filter fallback Desktop E2E query to only completed runs so in-progress runs with null conclusion don't cause false failures Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: fa055bb71ff8
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/release-gate.yml:
- Around line 129-133: The gh run list invocation that sets HEAD_STATUS (the
command assigning HEAD_STATUS using --workflow=e2e-desktop.yml ... --limit=5)
uses too small a --limit, causing valid runs for MAIN_SHA to be missed during
high activity; update all gh run list calls that target the e2e-desktop workflow
(the HEAD_STATUS assignment and the analogous commands around lines referenced)
to use a much larger --limit (e.g., 50 or 100) consistently to ensure the query
window covers recent activity and avoid false "no run found" results.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #252 +/- ##
=======================================
Coverage 46.31% 46.31%
=======================================
Files 106 106
Lines 8266 8266
Branches 591 591
=======================================
Hits 3828 3828
Misses 4271 4271
Partials 167 167
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
Bump --limit from 5/20 to 50 on gh run list queries for e2e-desktop.yml to avoid missing valid runs during periods of high workflow activity. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: 8e251b5e10a6
HEAD~1 only diffs the last commit, missing changes from earlier commits in multi-commit pushes. github.event.before captures the full push range correctly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: 9519b3358eb6
Summary
mainpush, causing the release gate to immediately fail with "no run found"timeout-minutes: 40job safety net to accommodate both polling phasespushtrigger from CI workflow (redundant — CI already runs on PRs, and E2E workflows handle post-merge verification)claude-code.ymlworkflow (no longer needed)Test plan
🤖 Generated with Claude Code