Skip to content

feat(account): add Azure & GitHub OAuth sign-in and cross-fork PRs#40

Open
t1gu1 wants to merge 44 commits into
devlint:mainfrom
t1gu1:feat/account-github-oauth
Open

feat(account): add Azure & GitHub OAuth sign-in and cross-fork PRs#40
t1gu1 wants to merge 44 commits into
devlint:mainfrom
t1gu1:feat/account-github-oauth

Conversation

@t1gu1
Copy link
Copy Markdown
Contributor

@t1gu1 t1gu1 commented Jun 5, 2026

Summary

This PR introduces a major overhaul of the Pull Request workflow and repository management, focusing on GitHub OAuth integration, cross-fork support, Azure DevOps compatibility, and
significant performance optimizations.

🔐 GitHub OAuth & Tokenless Workflow

  • Sign in with GitHub: New device-flow authentication in Settings > Accounts.
  • Keychain Security: Tokens are stored in the OS keychain and never exposed to the frontend.
  • REST-based PR Path: Activates a new tokenless REST path that removes the requirement for the gh CLI for core PR actions (listing, creation, merging, etc.).
  • Cross-Fork Support: Seamlessly handles PRs between forks and their upstream repositories, including listing and creation.

🏢 Azure DevOps Integration

  • Full Lifecycle Support: New AzureProvider for PR listing, creation, merging, and checkout.
  • Rich Features: Support for PR comments, CI check status (branch-policy evaluations), and reviewer votes/reviews.
  • Auto-Refresh: Implemented automatic access token refresh for uninterrupted workflows.

⚡ Performance & Responsiveness

  • PR Cache (SWR): Disk-persisted "Stale-While-Revalidate" cache for PR lists and details. The UI now paints instantly using cached data while revalidating in the background.
  • Async Backend: Converted Tauri commands to async, offloading blocking Git and network operations to background threads to prevent UI freezes.
  • libgit2 Fast Path: Optimized git_status using in-process libgit2, significantly reducing IPC overhead compared to spawning CLI processes.

🎨 UI/UX Enhancements

  • Standardized Avatars: Centralized avatar styling for a consistent "disk" look across all views.
  • Enhanced Status Visibility: Integrated CI check status directly into the sidebar's "waiting dot".
  • Smart Link Handling: External Markdown links now open in the system browser rather than the app webview.
  • Fluid Loading: Replaced manual refresh buttons with automatic spinners during background data fetches.

🛠 Other Improvements

  • GH CLI Guidance: Automatically guides users to account settings when gh CLI auth errors are detected.
  • Standardized "Open in Browser" labels and icons across all forge providers.
  • Optimized PR data loading to reduce redundant API calls.

!! IMPORTANT !!

For that PR i use a Github Client ID that i created to make the github auth works.
But it should the yours/the gitwand project.

Simply go here https://github.com/settings/developers and click on the top right button New Oauth App.
Be sure to have the ---> device flow enabled <---
Then use the given CLIENT ID instead of the one that i used.


Kinda the same thing with Azure

Go to: https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade

Steps:

  1. Name it (e.g. "GitWand").
  2. Supported account types → Accounts in any organizational directory (multi-tenant — matches organizations endpoint in code).
  3. Register. Copy Application (client) ID = your GITWAND_AZURE_CLIENT_ID.
  4. Left nav → Authentication → Allow public client flows = Yes (required for device flow). Save.

Why

  • Don't love to have to install gh and configure it (Less pain with oauth for the user)
  • The possibility to create and see fork PRs for a project is a game changing for contributors (me)
  • Azure was a missing platform/forge use a lot by entreprises
  • The app was kinda slow when we changed of context (The optimization part)

PRs is so a nice feature but without the forks functionality, i could not use it. :(

Test plan

  • Sign in with GitHub from Settings and confirm the account persists.
  • Open the PR view from a forked repo and verify the target selector defaults to upstream.
  • Create a same-repo PR and confirm no regression.
  • Verify the new UI strings render in each supported locale.

Tests that i did'nt do (If you have these in your setup, could be nice if you test it)

  • Create a cross-fork PR via both the REST and gh code paths.
  • Test the changes with GitLab
  • Test changes with BitBucket

Notes:

  • I dont try back when authenticated with gh
  • I dont test with the other services like Gitlab and Bitbucket
  • This PR request was made from GitWand from the fork! ✅

How it looks

image

Here the icon change from github to Azure (I fix it for every platforms)

image

PRs comments

image

Guillaume Huard Hughes added 9 commits June 5, 2026 06:00
🪄 Commit via GitWand
Quand `origin` est un fork, la vue de création de PR propose un sélecteur
de dépôt cible (parent upstream ou fork), avec upstream par défaut. Gère
les chemins REST (`fork-owner:branch`) et `gh` (`--repo`) ; nouvelle
commande `gh_fork_info` pour détecter la relation de fork.

🪄 Commit via GitWand
Users can now configure the language for AI-generated pull request titles and
descriptions to be either English (default) or match the app's UI locale.

Additionally, this commit replaces direct `window.open` calls with
`openExternalUrl` across various components. This ensures that external
links open correctly via the operating system's default browser when running
in the Tauri webview, where `window.open` is a no-op.
When the current repository is a fork, the PR list fetched via the GitHub
REST API will now include pull requests opened from the fork to its
upstream parent repository.

Operations like viewing PR details, diffs, checks, or merging will
also transparently resolve to the correct upstream repository for these
cross-repository pull requests, providing a more complete workflow.
Remove the unused `parent_default_branch` field from the `ForkInfo` struct.
Introduce an `upstream_parent` helper function to centralize the logic for
detecting when a repository is a fork of an upstream parent. This simplifies
PR listing and detail views for cross-repository pull requests.

Additionally, streamline the PR creation view for fork targets and standardize
external URL opening in `App.vue` for consistency.
When the GitHub CLI (`gh`) is not installed, the PR list sidebar now displays an enhanced error message including a hint and a button. Clicking this button directly opens the 'Accounts' tab in Settings. This helps users discover and configure GitHub authentication via the app's built-in OAuth process as an alternative to manual `gh auth login`.

This commit also introduces a generic mechanism to open the Settings panel to a specified tab and expands the range of available tab identifiers.
Set GitHub as the default forge when adding a new account and hide the
manual username input field for GitHub accounts. This anticipates
fetching the username via OAuth, removing a redundant input step for users.
Introduce Azure DevOps as a new forge, allowing users to authenticate via
Entra ID OAuth device flow and manage pull requests directly within the app.

This includes:
- **Entra ID Device Flow:** Authenticate using "Sign in with Azure" in Settings > Accounts, storing the token in the OS keychain.
- **Pull Request Workflow:** List, view details, diffs, files, create, merge, checkout, and convert draft PRs to ready states via the Azure DevOps REST API (v7.1).
- **Auto-detection:** Automatically identify Azure DevOps remotes (`dev.azure.com`, `*.visualstudio.com`).
- **Partial PR Intelligence:** Conflict preview and hotspot analysis are reused (local git-based).

Comments, reviews, reviewer pickers, and CI checks are not yet implemented.
Update 'Open in Browser' buttons to dynamically display the active forge's name (e.g., GitHub, GitLab) instead of a hardcoded 'GitHub'. The GitHub-specific icon has also been replaced with a generic external link icon. This ensures accurate labeling and visual representation across all supported code hosting platforms.
```
@t1gu1 t1gu1 force-pushed the feat/account-github-oauth branch from 89a080c to fe8d7f4 Compare June 5, 2026 11:50
@t1gu1 t1gu1 changed the title feat(account): add GitHub OAuth sign-in and cross-fork PRs feat(account): add Azure & GitHub OAuth sign-in and cross-fork PRs Jun 5, 2026
Guillaume Huard Hughes added 2 commits June 5, 2026 09:36
Prevent clicking http(s) links within rendered PR descriptions and comments from navigating the Tauri webview. Instead, intercept these clicks and open the URLs in the user's default external browser.
Azure DevOps access tokens expire after approximately 1 hour, leading to API failures and often returning an HTML sign-in page rather than a 401 status.

This change introduces an automatic token refresh mechanism to keep Azure DevOps sessions alive:
- Persists the Entra ID refresh token alongside the access token in the OS keychain.
- The `az_json` API wrapper detects authentication failures (including HTML responses) and attempts to exchange the refresh token for a new access token.
- If successful, the API request is retried with the new token, preventing frequent re-authentication and improving the reliability of the Azure DevOps integration.
@t1gu1
Copy link
Copy Markdown
Contributor Author

t1gu1 commented Jun 5, 2026

I fix some issue that i found.

  • When we clicked on a PR description link, it was open inside Gitwand instead of a browser.
  • Diff changes were not display correctly in the PRs list
  • Performance was not crazy when trying to see PRs and PR detail (And no caching)
  • Profile icons was not using the new style

Guillaume Huard Hughes added 6 commits June 5, 2026 10:15
Azure DevOps PR objects lack inherent file/line change statistics and organize comments into "threads."

This change:
- Populates PR `changed_files`, `additions`, and `deletions` by performing a local `git diff --numstat` between the source and target branches. This ensures the Files tab badge and related stats are correctly displayed.
- Adds support for listing and creating general PR comments, mapping Azure's "threads" into a flat comment list for the frontend.
- Synthesizes globally unique comment IDs for Azure threads to avoid collisions.

This enhances the Azure DevOps integration by providing previously missing PR comment functionality and improving the detail view with accurate file change statistics.
Azure DevOps integration now includes:
- **CI checks:** Fetches Azure branch policy evaluations (e.g., build validation, required reviewers) and maps them to CI checks, providing accurate status for merge readiness.
- **Reviews:** Retrieves Azure reviewer votes (approve, changes requested) and maps them to PR reviews, enabling users to submit votes and see approval status.

These enhancements complete key aspects of the Azure DevOps PR workflow, ensuring the merge-readiness chip accurately reflects both build and approval states.
…ewer status

This change refines Azure DevOps PR merge readiness checks by:
- Ensuring reliable policy evaluation fetching through explicit API version pinning (`7.1-preview.1`).
- Clarifying reviewer requirements by automatically spelling out policy names like "At least N reviewer(s) must approve".
- Introducing a fallback mechanism to surface "Waiting for reviewer approval" or "Changes requested" when explicit policy evaluations are unavailable.
- Updating the frontend to display specific failing/pending check names in the merge readiness banner, providing clearer reasons for unready PRs.
This change enhances the Azure DevOps PR experience by:

- Introducing a derived `review_decision` based on reviewer votes, which, along with merge status, powers a new yellow "waiting" dot in the PR list sidebar to quickly identify PRs needing attention.
- Calculating `additions` and `deletions` locally via `git diff --numstat` for each PR, as Azure's API does not provide these statistics directly on the PR object.
- De-duplicating policy names in merge readiness checks to avoid redundant entries when Azure reports the same policy multiple times.
This change improves the Pull Request experience across supported forges by:
- Reducing redundant `git fetch` calls for PR lists, fetching only on the first page during pagination.
- Deriving `review_decision` for GitHub PRs from `requested_reviewers` to enable accurate waiting status.
- Calculating additions and deletions locally for GitHub PRs, as they are absent from the list API.
- Refining the CI check evaluation logic to more accurately determine blocking checks for merge readiness.
This change enhances the GitHub Pull Request experience by:
- Fetching CI status rollups for PRs using a single batched GraphQL query, as
  the REST list API does not include this information.
- Incorporating the CI status into the PR list sidebar's "waiting" dot logic,
  allowing users to quickly identify PRs with pending or failing checks.
@t1gu1 t1gu1 marked this pull request as draft June 5, 2026 14:59
Guillaume Huard Hughes added 6 commits June 5, 2026 11:20
This change enhances the GitHub Pull Request detail view by displaying all associated comments.
- It fetches issue-level comments (general conversation comments not tied to a diff line) in addition to existing inline review comments.
- Both types are merged and presented chronologically in a new section below the PR description, offering a complete discussion history.
- The implementation includes robust API fetching via REST or `gh api` CLI fallback for unauthenticated scenarios.
This change enhances the Pull Request detail view by:
- Adding a "Go to" button next to each comment, allowing users to navigate directly to the comment's permalink on the web platform.
- Implementing platform-specific logic for these links: using direct comment URLs when available (e.g., GitHub, Bitbucket), and falling back to the PR URL with a `#note_` anchor for GitLab.
- Filtering out GitLab system notes (e.g., "changed description", label events) from the displayed comments list to ensure only actual conversation comments are shown.
This change unifies the appearance of author avatars in Pull Request components (comments, details, reviewer lists). Avatars now consistently use the outline style: a transparent fill, a deterministically colored border, and initials. This brings visual consistency with other parts of the application, such as the Dashboard and CommitGraph.
Extrait la logique dupliquée (couleur, initiales) de 9 composants
vers un composable unique pour uniformiser le rendu des avatars.

🪄 Commit via GitWand
…Request lists and detailed views, stored on disk. This significantly enhances perceived performance by:

- Instantly painting cached PR data on repo-switch or app cold start.
- Revalidating data in the background without blocking the UI.
- Displaying subtle refreshing indicators (spinners/badges) during background revalidation, distinguishing it from full-page cold loads.
- Gracefully handling offline scenarios by displaying cached data instead of empty states.

The cache includes LRU eviction and age-based pruning to manage storage footprint, and robust error handling for storage quota issues.
Move long-running Tauri commands (Azure API calls, Git operations) to background threads using `tauri::async_runtime::spawn_blocking`. This prevents UI freezes during blocking network or process I/O, maintaining application responsiveness.

A related change prevents `loadMorePrs` from firing duplicate pagination requests during SWR revalidation, avoiding redundant slow API calls.
@t1gu1
Copy link
Copy Markdown
Contributor Author

t1gu1 commented Jun 5, 2026

There is a new big change on performance side that change everything.
The app feels way faster and reactive now!

It offload blocking commands to background threads

At first, it was for the PRs but it was feeling way too nice to not extend it to all the app.


Example:

Move long-running Tauri commands (Azure API calls, Git operations) to background threads using tauri::async_runtime::spawn_blocking. This prevents UI freezes during blocking network or process I/O, maintaining application responsiveness.

A related change prevents loadMorePrs from firing duplicate pagination requests during SWR revalidation, avoiding redundant slow API calls.


It is more than 174 commands converted from sync fn → async fn across every command file.

Added to that, we added some cache on PRs to makes it feels even more reactive.
Still sync while seeing it. (We see some loading indicators)

Guillaume Huard Hughes added 2 commits June 5, 2026 12:28
Migrate `#[tauri::command]` functions to `async fn` to enable asynchronous execution. This allows these commands to yield control to the Tauri runtime during I/O operations (e.g., network requests, file system access, external process execution), preventing the UI thread from blocking and further enhancing application responsiveness.
This change improves the visual feedback for the Pull Request list. During initial data loading or background stale-while-revalidate (SWR) revalidations, the refresh button is now replaced by an active spinner. This provides a clearer indication that data is being fetched and prevents users from attempting to re-trigger a refresh while an operation is already in progress.
@t1gu1 t1gu1 marked this pull request as ready for review June 5, 2026 16:44
Guillaume Huard Hughes added 19 commits June 5, 2026 12:53
Previously, when working in a local clone of a forked repository, the application might not have accurately listed or counted all relevant pull requests, especially those opened against the upstream parent.

This change modifies the PR listing and counting logic to first identify the canonical base repository (the parent for forks) and then query that repository. This aligns the application's behavior with the `gh pr list` CLI, which implicitly targets the base repository, ensuring comprehensive and accurate PR visibility regardless of whether the user is in the fork's local clone.
The Azure DevOps API does not provide accurate comment counts within the PR object. This change populates the `reviewComments` field from the actual list of fetched comments for Azure DevOps PRs.

Additionally, a safeguard is applied to ensure the displayed comment count in both the PR detail view and panel is always at least the number of comments that have actually been fetched and rendered, preventing discrepancies.
Azure DevOps uses a query parameter structure (e.g., `?_a=commits`) for PR detail tabs like commits, files, and checks, unlike other forges that use path segments (e.g., `/commits`).

This change introduces forge-aware URL construction for these links, ensuring they open correctly in the browser for Azure DevOps pull requests.
Moves the "Commits", "Files", and "CI" links to more prominent positions in both the PR detail view and the PR panel. In the detail view, they are now "hero" links in the header. In the PR panel, they are compact "mini" links grouped with the main forge link.

This enhances discoverability and provides quicker access to these external resources.
Replaces the previous custom, limited markdown renderer with the MarkdownIt library.
This change enables comprehensive Markdown formatting for pull request comments
and descriptions, including headings, lists, inline code, and fenced code blocks.

This enhances the readability and expressiveness of PR content within the application.
Ensures the CSS custom property value for the suggestion label is correctly quoted,
preventing potential parsing issues if the label itself contains special characters
or if the browser's CSS parser has issues with the double quotes within the template literal.
Introduces consistent red/yellow/green indicators for PR health in both
the list sidebar and detail view.

This change aggregates check, build, and pipeline statuses from the
respective APIs (Azure DevOps policies, Bitbucket commit statuses, GitHub
check-runs, and GitLab pipelines). It fixes previous inaccuracies where
pending or failing checks were sometimes missed, particularly for GitHub,
and uses parallel fetching for improved performance on PR lists.
```
The "no approval" message was previously shown even when all checks passed and no
changes were requested. This change hides the generic "no approval" waiting
banner in such cases, as the PR is functionally just waiting for a final merge
and isn't blocked by active work. Named reviewer policies are still surfaced.
Azure DevOps often reports the same policy twice (e.g., inherited vs. branch-level). This consolidates duplicate checks, prioritizing the most resolved status (e.g., SUCCESS over PENDING) to provide a clearer, more accurate overview of PR health.
Azure DevOps build-validation policies can report 'queued' even if the underlying build
has already completed (and possibly failed). This update fetches the actual build
outcome to ensure the PR status accurately reflects reality.

Additionally, a virtual 'Merge Conflict' check is now added to the CI tab for
unmergeable PRs. This clearly flags the critical blocker and incorporates it into
the overall merge readiness assessment.
Azure DevOps policies for builds can appear generically, leading to incorrect
de-duplication. This update ensures distinct build definitions are treated as
separate checks by including their ID in the de-duplication key.

Additionally, Azure's "Expired (Please Re-queue)" status is now recognized
and surfaced with a warning, clearly indicating that a build needs to be
re-run to resolve a merge block. This was previously treated as a generic
pending state.
Previously, draft PRs were always shown as "ok" (green) in the sidebar,
regardless of their actual CI status. This change ensures that draft PRs
also reflect their underlying CI health, providing a more accurate
visual indicator (e.g., red for failing checks).
The displayed merge status now intelligently factors in the CI state,
preventing a misleading "Mergeable" status when checks are red. It will
show "Problem detected" if CI is failing, or "Conflicting" if there are
Git conflicts.

Additionally, the merge status labels are now localized for a more
user-friendly experience.
Consolidates GitHub and Azure device authorization grant logic into a shared
`useDeviceFlowAuth` composable, improving code reuse and maintainability for
authentication workflows.

Enhances PR list performance by parallelizing diff calculations for additions
and deletions.

Optimizes markdown rendering for PR descriptions and comments by pre-rendering
HTML and centralizing external link handling, reducing re-renders and improving
UI responsiveness.

Standardizes checks for merge conflicts across PR components for consistency.
Integrates `can_merge` status into pull request details across all forges.
The merge button is now proactively disabled when the current viewer lacks
permission to merge the PR. Forges that do not cheaply expose this
information (Azure, Bitbucket) default to `None`, ensuring the UI only
gates on actual errors rather than an unknown permission.
Previously, the `can_merge` status for GitHub pull requests could be inaccurate,
especially in fork-based workflows. The logic incorrectly checked permissions
against the working directory's repository or relied on incomplete API
responses, leading to misreported merge capabilities.

This update ensures merge permissions are accurately determined by explicitly
querying the PR's actual *base* repository, where the merge operation would
occur, for both `gh` CLI and GitHub REST API paths.
The 'Open in Browser' button is now positioned more prominently at the beginning of the PR detail view's action row. Its style has also been updated from a secondary (ghost) button to a standard primary button, improving visibility and discoverability for this frequently used action.
Introduces a 5-minute background revalidation mechanism for the active PR
panel (detail view or list). This prevents data from going stale in
long-open panels by periodically refreshing the displayed information.

The revalidation is visibility-gated, meaning it automatically pauses
when the application tab is hidden and resumes when visible, adhering
to performance discipline by not consuming resources unnecessarily.
Adjusts title spacing to prevent it from consuming all available horizontal
space and ensures proper right-alignment for accompanying action elements.
@t1gu1
Copy link
Copy Markdown
Contributor Author

t1gu1 commented Jun 5, 2026

@devlint Huge PR here, but a lot of news and tweaks around PRs and a lot of optimizations!

This is a really nice PR that unlocks PRs functionalities for other platforms, forks and makes it globally more accessible.

Don't forget to read the "!! IMPORTANT !!" section of the first comment where you should take a time to replace some public CLIENT ID keys. (I mean it works with the current keys, but i think you should own these to be able to manage it more)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant