Skip to content

fix(onboarding): Handle repo selection race with background link_all_repos#111699

Closed
jaydgoss wants to merge 13 commits intojaygoss/vdy-24-scm-platform-features-step-ui-polish-and-analytics-passfrom
jaygoss/fix-repo-selection-race-with-link-all-repos
Closed

fix(onboarding): Handle repo selection race with background link_all_repos#111699
jaydgoss wants to merge 13 commits intojaygoss/vdy-24-scm-platform-features-step-ui-polish-and-analytics-passfrom
jaygoss/fix-repo-selection-race-with-link-all-repos

Conversation

@jaydgoss
Copy link
Copy Markdown
Member

@jaydgoss jaydgoss commented Mar 27, 2026

Fix repo selection in the SCM onboarding connect step to handle the race with the background link_all_repos task.

After a GitHub integration is installed, link_all_repos runs async and registers all repos. The old approach cached existing repos on mount and checked that cache before deciding to POST. This broke because the cache was often stale (task still running) and the repos endpoint is paginated (specific repo might not be on page 1).

New approach:

  • GET first with a targeted query filtered by repo name (sidesteps pagination)
  • POST only if the repo doesn't exist yet

The old code also hid (soft-deleted) repo records when the user deselected or switched repos. This made sense when repos were manually registered one at a time, but with link_all_repos auto-registering everything, hiding repos on deselect was counterproductive -- it removed records the background task created, causing them to disappear from the integration settings page. Repo selection is now just a context pointer with no side effects on the repo records themselves.

Also switches to queryClient.fetchQuery + fetchDataQuery for the imperative GET instead of deprecated Client.requestPromise.

@github-actions github-actions bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Mar 27, 2026
@jaydgoss jaydgoss marked this pull request as ready for review March 27, 2026 00:49
@jaydgoss jaydgoss requested a review from a team as a code owner March 27, 2026 00:50
@jaydgoss jaydgoss changed the base branch from master to jaygoss/vdy-24-scm-platform-features-step-ui-polish-and-analytics-pass March 27, 2026 15:58
@jaydgoss jaydgoss requested review from a team as code owners March 27, 2026 15:58
…repos

After a GitHub integration is installed, link_all_repos runs async and
may still be populating repos when the user reaches the repo selector.
The previous approach cached existing repos on mount and looked them
up before deciding whether to POST, but the cache was often stale or
paginated, causing selection to fail silently.

Now always POST first. If the repo already exists (background task or
previous session created it), the POST fails and we fall back to a
targeted GET filtered by repo name to find the existing record. This
avoids both the stale cache and pagination issues.
Flip the order: do a targeted GET filtered by repo name first, and
only POST if the repo doesn't exist yet. This avoids expected 400s
showing up in devtools and Sentry when the background link_all_repos
task has already created the repo.
Replace direct Client.requestPromise usage with fetchMutation which
wraps the same call but is the recommended API.
jaydgoss added 10 commits March 27, 2026 10:59
fetchMutation only accepts PUT/POST/DELETE methods. Use the shared
QUERY_API_CLIENT instance directly for the imperative GET call.
Replace deprecated QUERY_API_CLIENT.requestPromise with the sanctioned
queryClient.fetchQuery + fetchDataQuery pattern for imperative GET
requests outside of React Query hooks.
Use ApiQueryKey type with getApiUrl for proper URL typing, satisfying
the queryKey constraint on queryClient.fetchQuery.
With link_all_repos running in the background after integration
install, all repos are automatically registered in Sentry. The
hide-on-deselect and cleanup-on-switch logic was designed for manual
repo registration and is now counterproductive — it removes repo
records that the background task created, causing them to disappear
from settings. Selection is now just a context pointer.
Rewrite tests to match the GET-first-then-POST approach and removal
of repo hide/cleanup logic. Remove tests for cleanup-on-switch and
hide-on-remove since those behaviors no longer exist.
Match on r.name === repo.identifier instead of externalSlug because
externalSlug varies by provider (GitLab uses a numeric project ID,
VSTS uses external_id). Repository.name is consistently the full
repo path across all providers.
…rage

Remove unnecessary async from handleRemove test to fix require-await
lint error. Rename misleading test name to accurately reflect that only
POST fails (GET succeeds with empty results). Add dedicated test for GET
failure scenario. Simplify busy state test by removing waitFor dance
that couldn't observe the intermediate state.
@jaydgoss jaydgoss force-pushed the jaygoss/fix-repo-selection-race-with-link-all-repos branch from b866d17 to 03797dc Compare March 27, 2026 16:00
@jaydgoss
Copy link
Copy Markdown
Member Author

Closing to re-open with correct base — the base change auto-requested a ton of CODEOWNERS reviewers.

@jaydgoss jaydgoss closed this Mar 27, 2026
jaydgoss added a commit that referenced this pull request Mar 30, 2026
…repos (#111716)

Fix repo selection in the SCM onboarding connect step to handle the race
with the background `link_all_repos` task.

After a GitHub integration is installed, `link_all_repos` runs async and
registers all repos. The old approach cached existing repos on mount and
checked that cache before deciding to POST. This broke because the cache
was often stale (task still running) and the repos endpoint is paginated
(specific repo might not be on page 1).

New approach:
- GET first with a targeted query filtered by repo name (sidesteps
pagination)
- POST only if the repo doesn't exist yet

The old code also hid (soft-deleted) repo records when the user
deselected or switched repos. This made sense when repos were manually
registered one at a time, but with `link_all_repos` auto-registering
everything, hiding repos on deselect was counterproductive -- it removed
records the background task created, causing them to disappear from the
integration settings page. Repo selection is now just a context pointer
with no side effects on the repo records themselves.

Also switches to `queryClient.fetchQuery` + `fetchDataQuery` for the
imperative GET instead of deprecated `Client.requestPromise`.

Replaces #111699 (closed due to CODEOWNERS auto-review noise from base
change).
dashed pushed a commit that referenced this pull request Apr 1, 2026
…repos (#111716)

Fix repo selection in the SCM onboarding connect step to handle the race
with the background `link_all_repos` task.

After a GitHub integration is installed, `link_all_repos` runs async and
registers all repos. The old approach cached existing repos on mount and
checked that cache before deciding to POST. This broke because the cache
was often stale (task still running) and the repos endpoint is paginated
(specific repo might not be on page 1).

New approach:
- GET first with a targeted query filtered by repo name (sidesteps
pagination)
- POST only if the repo doesn't exist yet

The old code also hid (soft-deleted) repo records when the user
deselected or switched repos. This made sense when repos were manually
registered one at a time, but with `link_all_repos` auto-registering
everything, hiding repos on deselect was counterproductive -- it removed
records the background task created, causing them to disappear from the
integration settings page. Repo selection is now just a context pointer
with no side effects on the repo records themselves.

Also switches to `queryClient.fetchQuery` + `fetchDataQuery` for the
imperative GET instead of deprecated `Client.requestPromise`.

Replaces #111699 (closed due to CODEOWNERS auto-review noise from base
change).
@github-actions github-actions bot locked and limited conversation to collaborators Apr 12, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant