Conversation
…ndpoint Cache the repo list and start fetching pull requests as repo pages arrive instead of waiting for the full workspace scan to finish, cutting cold-start time for large workspaces. "Search My Open Pull Requests" was returning 404s because Bitbucket removed the workspace-wide "PRs for a user" endpoint it depended on; it now reuses the same per-repo scan as Search All Open Pull Requests, filtered server-side to the current user. Also adds an optional per-command "Max Repository Age (days)" preference (0 = no limit) so workspaces with many stale repos can skip them entirely, reducing the risk of hitting Bitbucket's rate limit during a full scan. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Thank you for your contribution! 🎉 🔔 @Lp-Francois @esarmstrong @itsrifat @skuio @arpitdalal @LitoMore @AaronMoat @0xdhrv @Siuhinnn you might want to have a look. You can use this guide to learn how to check out the Pull Request locally in order to test it. 📋 Quick checkout commandsBRANCH="bitbucket-limit-stale-repo-scans"
FORK_URL="https://github.com/sunnywty/raycast_extensions.git"
EXTENSION_NAME="bitbucket"
REPO_NAME="raycast_extensions"
git clone -n --depth=1 --filter=tree:0 -b $BRANCH $FORK_URL
cd $REPO_NAME
git sparse-checkout set --no-cone "extensions/$EXTENSION_NAME"
git checkout
cd "extensions/$EXTENSION_NAME"
npm install && npm run devWe're currently experiencing a high volume of incoming requests. As a result, the initial review may take up to 15 business days. |
|
…caching
- Scope the internal repo-list cache key by account email too, so switching
Bitbucket accounts doesn't reuse another account's cached repository list
- Include maxRepoAgeDays in both PR-result SWR cache keys so changing the
preference invalidates the previous scope instead of showing a stale result
- Don't fail the whole scan if persisting the repo-list cache fails; log and
continue, since the actual API work already succeeded
- Use Title Case for the "Max Repository Age (Days)" preference title
- Use {PR_MERGE_DATE} in CHANGELOG.md per repo convention
- Replace the hand-written Preferences interface with Raycast's generated
per-command types (maxRepoAgeDays only exists on the two commands that
scan repos, not on the shared extension preferences)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
zod was only used to validate the now-removed dead "PRs for a user" endpoint response; nothing in src imports it anymore. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
pernielsentikaer
left a comment
There was a problem hiding this comment.
Hi @Lp-Francois 👋
We're reviewing PR #31240 and I'd like your take as the extension author before we move ahead — do you consider any of this breaking for existing users?
The main change is Search My Open Pull Requests: Bitbucket removed the workspace-wide .../pullrequests/{user} endpoint it relied on (that was the 404), so it now scans each repository and filters per repo with q=author.uuid="…". Same command name and UI, but results now depend on every repo scan succeeding, and it honours the new repo-age setting.
It also adds a per-command Max Repository Age (Days) preference (default 0 = unchanged) and a 10-minute repository-list cache, and the PR cache keys changed, so the first run after upgrading re-scans.
Command names/IDs, existing preferences, and the author/contributors metadata are unchanged. Does that look safe to you as a non-breaking fix, or is there behaviour here (e.g. what the old "my PRs" endpoint actually returned) that would break existing setups? 🙂
I’ll convert this PR into a draft after submitting this review. Please press Ready for review when it’s ready and we’ll have a look 😊
The removed Bitbucket "PRs for a user" endpoint returned PRs the user authored OR was a requested reviewer on. The per-repo replacement query only matched author.uuid, silently narrowing results for anyone who used "Search My Open Pull Requests" to see PRs awaiting their review. Broaden the q filter to (author.uuid OR reviewers.uuid) to preserve that scope. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Thanks for the review, @pernielsentikaer! I'm the one who made these changes (not the original extension author), so let me answer directly: Not breaking, and here's why: "Search My Open Pull Requests" is currently returning a 404 for every user today, on the version already in the store. It calls Good catch prompting a real fix: your question made me go verify the old endpoint's exact scope instead of assuming. That endpoint historically returned PRs the user authored or was a requested reviewer on (dashboard-style), but my per-repo replacement was only filtering on "Search All Open Pull Requests" behavior is unchanged by default: the new "Max Repository Age (Days)" preference defaults to Cache key changes are internal/ephemeral only: it's an in-memory + local-disk performance cache, not user data. Worst case after upgrading is one slightly slower first search while it repopulates — nothing is lost. Command names/IDs and existing preferences are all unchanged, so this should be safe to review as a non-breaking fix + opt-in perf improvement. Happy to answer anything else. |
…-repo-scans # Conflicts: # extensions/bitbucket/CHANGELOG.md # extensions/bitbucket/src/components/pullRequests/searchAllPullRequests.tsx # extensions/bitbucket/src/components/pullRequests/searchMyPullRequests.tsx # extensions/bitbucket/src/queries/index.ts
Sorting by -updated_on while paginating a live, actively-pushed workspace can shift a repo's rank between page fetches, causing it to reappear on a later page. That repo's PRs then get fetched and rendered twice (visible as React duplicate-key warnings and duplicated list rows). De-dupe by repo slug as pages arrive. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
I’d like to hear from @Lp-Francois, the original author. I’ll give him two days to check in before going further 🙂 |
| // away from just being a filter): https://community.atlassian.com/forums/Bitbucket-articles/Reminder-List-pull-requests-for-a-user-API-removal/ba-p/2935311 | ||
| // so "my open PRs" reuses the same per-repo scan as getAllOpenPullRequests, with the | ||
| // author-or-reviewer filter applied server-side per repo via the `q` query param. | ||
| export async function getMyOpenPullRequests( |
There was a problem hiding this comment.
This is now N+1 API calls, could we hit rate limits because of this?
| // repo older than the cutoff is seen instead of scanning the whole workspace. Yields pages | ||
| // as they arrive so callers can start PR-fetching before later pages have loaded. | ||
| async function* iterateAllRepositories(): AsyncGenerator<RepoWithSlug[]> { | ||
| const cutoff = maxRepoAgeMs(); |
There was a problem hiding this comment.
this can throw if preferences are invalid somehow
We should probably put a queue.close in a finally and wrap the rest in try{}. Wdyt?
There was a problem hiding this comment.
Good catch — this can indeed throw (bad maxRepoAgeDays, a failed repo-list API call, etc.) before every repo is queued, which would leave the worker pool awaiting queue.next() forever. Just pushed a fix: wrapped feedRepos's body in try/finally so queue.close() always runs regardless of where it throws (commit 6e1296f).
If getCachedRepositories, the repo-listing API call, or preference validation (maxRepoAgeMs) throws before every repo is queued, queue.close() never ran — leaving the 10 worker loops awaiting queue.next() forever, only cleaned up when the command process exits. Move queue.close() into a finally so it always runs. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…g them The N+1 per-repo scan (inherent to Bitbucket's API — no workspace-wide PR endpoint exists) can hit rate limits on large workspaces. Previously a 429 on a single repo permanently dropped that repo's PRs from the results (counted in failedRepoCount, never retried). Add retry-with-backoff for 429/5xx on both the repo-listing and per-repo PR-listing calls, honoring Bitbucket's Retry-After header when present. Concurrency stays at 10, unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…on hyperactive repos Bitbucket's `page` param is an offset, not a stable cursor. On a repo with PRs opened continuously during the scan, new PRs shift already-seen PRs into the next page's offset window, re-returning them — observed as duplicate PR rows (React duplicate-key warnings) and, in the worst case, a pagination loop that never terminates (report of the dev process running out of memory). De-dupe by PR id within a repo's own pagination, track how many new PRs each page actually contributes, and stop as soon as a page contributes nothing new (we've caught up to already-seen data) or a 40-page cap is hit, instead of relying solely on `!data.next`. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Found and fixed a real bug while testing this: on a handful of very actively-developed repos in a large workspace, "Search My Open Pull Requests" was intermittently rendering duplicate PR rows (React duplicate-key warnings) and, in one case, causing the process to run out of memory. Root cause: Bitbucket's Fix (commit e48a0bb): de-dupe by PR id within a repo's own pagination, track how many new PRs each page actually contributes, and stop as soon as a page contributes nothing new — instead of relying solely on |
The store guidelines ask every extension to declare at least one category; this one had none. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ailure SWR's default shouldRetryOnError retries a failed fetcher indefinitely in the background. If the repo-listing call itself exhausts our own withRetry attempts under sustained rate limiting, that rejects the whole scan, and SWR would then silently restart it from scratch, compounding with our per-request retries into a scan that "never stops." We already retry transient errors per-request and surface a toast on failure, so disable SWR's own retry-on-error. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Search Repositories shares the same cacheConfig but has no retry logic of its own around its direct Bitbucket call, so disabling SWR's automatic retry there would leave a transient network/rate-limit/server error stuck with no way to recover. Split it into a separate scanCacheConfig used only by Search All / Search My Open Pull Requests, which do retry per-request. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Do you want to check it again @Lp-Francois |
Summary
qquery param.0= no limit) that skips repositories not updated within N days.Why the age-limit preference matters
I have 100+ repositories in my workspace, and most of them are stale (no recent activity, no open PRs). Both search commands have to make one API call per repository (Bitbucket has no workspace-wide "list PRs" endpoint), so a full scan across all of them sometimes triggers Bitbucket's rate limiting, causing failed/incomplete results. Letting a workspace skip long-dormant repos entirely cuts both the number of API calls and the chance of getting rate-limited, while defaulting to
0(scan everything) keeps existing behavior unchanged for anyone who doesn't set it.Test plan
npm run build/ray lintpass with no errorsray develop: both "Search All Open Pull Requests" and "Search My Open Pull Requests" load results correctly, including with the age preference set and unset🤖 Generated with Claude Code