Skip to content

feat: Add Azure DevOps repository support#487

Open
sanjay3290 wants to merge 8 commits intoAsyncFuncAI:mainfrom
sanjay3290:feat/azure-devops-support
Open

feat: Add Azure DevOps repository support#487
sanjay3290 wants to merge 8 commits intoAsyncFuncAI:mainfrom
sanjay3290:feat/azure-devops-support

Conversation

@sanjay3290
Copy link

Summary

Adds Azure DevOps as a supported repository provider alongside GitHub, GitLab, and Bitbucket.

  • Clone support: PAT-based authentication for dev.azure.com repositories (handles both https://dev.azure.com/org/project/_git/repo and https://user@dev.azure.com/... URL formats)
  • File content API: REST API integration using Azure DevOps Items API v7.0 with Basic auth
  • Frontend: Platform selector button, URL auto-detection, file tree + README fetching, Azure DevOps icon
  • Repo type: Uses azure_devops (distinct from existing azure LLM provider)

Closes #314

Changes

Area Files Description
Backend api/data_pipeline.py Clone auth, repo name extraction, file content retriever, URL username stripping
Backend api/api.py, api/simple_chat.py, api/websocket_wiki.py Updated type field docs
Frontend src/components/TokenInput.tsx Added azure_devops to platform type + button
Frontend src/components/ConfigurationModal.tsx Platform selector always visible, auto-expand PAT for ADO
Frontend src/app/page.tsx URL parsing for dev.azure.com, example URL
Frontend src/app/[owner]/[repo]/page.tsx Repo type detection, file tree fetching, ADO icon
Frontend src/components/ModelSelectionModal.tsx Updated platform type union
Tests test/test_extract_repo_name.py ADO URL test cases
Tests test/test_azure_devops_file_content.py File content retrieval tests

Testing

  • All 11 Python tests pass (4 new ADO + 7 existing)
  • Next.js production build succeeds
  • Tested end-to-end with a real Azure DevOps private repository using PAT authentication
  • Verified clone, file content retrieval, and wiki generation pipeline

Test plan

  • Verify Azure DevOps platform button appears in Configure Wiki dialog
  • Test with public ADO repo URL (https://dev.azure.com/org/project/_git/repo)
  • Test with user-prefixed URL (https://user@dev.azure.com/org/project/_git/repo)
  • Test PAT authentication for private ADO repos
  • Verify existing GitHub/GitLab/Bitbucket flows are unaffected
  • Run python -m pytest test/ -v
  • Run npm run build

- Add PAT-based authentication for azure_devops repo type in download_repo()
  using the format https://{token}@dev.azure.com/org/project/_git/repo
- Add _extract_repo_name_from_url() handling for Azure DevOps URLs,
  parsing the _git path segment to extract project and repo name
- Add test cases covering standard ADO URLs, .git suffix, and trailing slash
Add get_azure_devops_file_content() function that fetches file contents
from Azure DevOps repositories using the REST API with PAT-based Basic
auth. Update the get_file_content() dispatcher to route azure_devops
repo type to the new function. Include unit tests for URL parsing,
auth header construction, and dispatcher routing.
Update platform type unions across all components to include
'azure_devops' and add the Azure DevOps selection button in the
token input platform picker.
- Add dev.azure.com domain detection in parseRepositoryInput() to set
  type as 'azure_devops'
- Parse ADO URL structure (dev.azure.com/{org}/{project}/_git/{repo})
  extracting project as owner and repo name correctly
- Update repoType detection in repo page to recognize dev.azure.com host
Add createAzureDevOpsHeaders helper for Basic auth and implement
the azure_devops branch in the file tree fetching logic. This uses
the ADO Items API with full recursion to retrieve the repo structure
and fetches README.md content for wiki generation.
- Add FaMicrosoft icon for azure_devops repo type in repo info display
- Add Azure DevOps example URL in Quick Start section on home page
Add azure_devops to the list of supported repository types in field
descriptions across simple_chat.py, websocket_wiki.py, and api.py.
- Strip username prefix from ADO URLs (user@dev.azure.com) before cloning
- Fix API URL construction for ADO file content with user@ URLs
- Show platform selector (GitHub/GitLab/Bitbucket/Azure DevOps) directly
  in the Configure Wiki dialog instead of hiding behind token toggle
- Auto-expand PAT input when Azure DevOps is selected
- Add gemini-3.1-flash-lite-preview to Google model list
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly expands the application's capabilities by introducing comprehensive support for Azure DevOps repositories. Users can now seamlessly interact with their ADO projects, including private ones, by providing a PAT. This integration ensures a consistent experience across various Git providers, allowing for repository cloning, file access, and wiki generation directly from Azure DevOps.

Highlights

  • Azure DevOps Integration: Full support has been added for Azure DevOps repositories, enabling cloning, file content retrieval, and wiki generation.
  • PAT-based Authentication: Personal Access Token (PAT) based authentication is now supported for Azure DevOps, handling both cloning and API access for private repositories.
  • Frontend Enhancements: The user interface has been updated to include Azure DevOps as a platform option, with automatic URL detection, file tree display, and README fetching.
  • API Integration: The backend now integrates with the Azure DevOps Items API v7.0 for efficient file content retrieval using Basic authentication.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • api/api.py
    • Updated the RepoInfo model to include azure_devops as a supported repository type.
  • api/config/generator.json
    • Added configuration for the gemini-3.1-flash-lite-preview model.
  • api/data_pipeline.py
    • Implemented PAT-based authentication for Azure DevOps repository cloning, including stripping existing usernames from URLs.
    • Added a new function get_azure_devops_file_content to retrieve file content using the Azure DevOps REST API v7.0 with Basic authentication.
    • Modified the general get_file_content dispatcher to route requests for azure_devops type to the new ADO-specific function.
    • Extended the _extract_repo_name_from_url method to correctly parse repository names from Azure DevOps URLs.
  • api/simple_chat.py
    • Updated the type field description in ChatCompletionRequest to explicitly include azure_devops.
  • api/websocket_wiki.py
    • Updated the type field description in ChatCompletionRequest to explicitly include azure_devops.
  • src/app/[owner]/[repo]/page.tsx
    • Added the FaMicrosoft icon for visual representation of Azure DevOps repositories.
    • Implemented createAzureDevOpsHeaders for handling authentication headers for ADO API calls.
    • Updated the repository type detection logic to correctly identify dev.azure.com URLs as azure_devops.
    • Added logic to fetch the file tree and README content from Azure DevOps repositories using their API.
    • Updated the repositoryType prop type for ConfigurationModal to include azure_devops.
  • src/app/page.tsx
    • Updated the selectedPlatform state type to include azure_devops.
    • Enhanced URL parsing to automatically detect Azure DevOps URLs and extract the project and repository names.
    • Added an example Azure DevOps URL to the input field for user guidance.
  • src/components/ConfigurationModal.tsx
    • Updated the selectedPlatform prop types to include azure_devops.
    • Modified the showTokenSection state to auto-expand the token input when Azure DevOps is selected, as PATs are often required.
    • Refactored the platform selection UI to always display platform buttons, including a new one for Azure DevOps.
    • Set allowPlatformChange to false for the TokenInput component, as platform selection is now handled directly in this modal.
  • src/components/ModelSelectionModal.tsx
    • Updated the repositoryType prop types to include azure_devops.
  • src/components/TokenInput.tsx
    • Updated the selectedPlatform prop types to include azure_devops.
    • Adjusted the display name for the 'azure_devops' platform to 'Azure DevOps' for better readability.
    • Added an Azure DevOps button to the platform selection options within the component.
  • test/test_azure_devops_file_content.py
    • Added a new test file containing unit tests for Azure DevOps file content retrieval, including dispatching, URL parsing, and basic authentication.
  • test/test_extract_repo_name.py
    • Added new test cases to verify the correct extraction of repository names from various Azure DevOps URL formats.
Activity
  • The author, sanjay3290, has implemented the core functionality for Azure DevOps support.
  • All 11 Python tests passed, including 4 new tests specifically for Azure DevOps.
  • The Next.js production build was successful.
  • End-to-end testing was performed with a real private Azure DevOps repository using PAT authentication.
  • Verification confirmed successful cloning, file content retrieval, and wiki generation for ADO repositories.
  • A detailed test plan has been provided for further review and validation.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces comprehensive support for Azure DevOps repositories, including cloning, file content retrieval via REST API, and frontend integration. However, it's critical to address several security vulnerabilities, primarily the lack of validation for user-provided repository URLs, which could lead to Server-Side Request Forgery (SSRF) and the leakage of sensitive Personal Access Tokens (PATs). Additionally, some URL construction lacks proper encoding, potentially allowing parameter injection. There's also a bug in the frontend URL parsing for ADO repositories, and opportunities to improve maintainability by extracting hardcoded values into constants.

Comment on lines +124 to +125
hostname = parsed.hostname or parsed.netloc.split('@')[-1]
clone_url = urlunparse((parsed.scheme, f"{encoded_token}@{hostname}", parsed.path, '', '', ''))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The hostname extracted from the user-provided repo_url is used to construct the clone URL without validation. This can lead to SSRF and credential leakage if an attacker provides a URL pointing to a malicious server, as the encoded_token (PAT) will be included in the request sent to that server.

Comment on lines +722 to +724
hostname = parsed_url.hostname or parsed_url.netloc.split('@')[-1]
project_path = '/'.join(path_parts[:git_index])
api_base = f"{parsed_url.scheme}://{hostname}/{project_path}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The repo_url is used to construct an API base URL without validating the hostname. This allows an attacker to perform SSRF by providing a malicious URL. When requests.get is called on line 734, the user's Azure DevOps PAT will be sent in the Authorization header to the attacker-controlled host.

throw new Error('Invalid Azure DevOps repository URL');
}

const adoRepo = adoParts[gitIndex + 1];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The repository name extracted from the Azure DevOps URL doesn't account for a potential .git suffix. If the URL is .../_git/myrepo.git, adoRepo will be myrepo.git, which will cause subsequent API calls to fail. You should remove the .git suffix, similar to how it's handled in the backend Python code and other parts of the frontend.

Suggested change
const adoRepo = adoParts[gitIndex + 1];
const adoRepo = adoParts[gitIndex + 1].replace(/\.git$/, '');

hostname = parsed_url.hostname or parsed_url.netloc.split('@')[-1]
project_path = '/'.join(path_parts[:git_index])
api_base = f"{parsed_url.scheme}://{hostname}/{project_path}"
api_url = f"{api_base}/_apis/git/repositories/{repo_name}/items?path={file_path}&api-version=7.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The repo_name and file_path variables are concatenated into the api_url without URL encoding. This can lead to URL parameter injection or path manipulation if these variables contain special characters like ?, &, or #. It is recommended to use urllib.parse.quote for these variables. Additionally, the API version 7.0 is hardcoded; consider defining it as a constant (e.g., ADO_API_VERSION = "7.0") at the top of the file for better maintainability and easier updates.

api_url = f"{api_base}/_apis/git/repositories/{quote(repo_name)}/items?path={quote(file_path)}&api-version={ADO_API_VERSION}"

}

const adoRepo = adoParts[gitIndex + 1];
const adoBase = `${adoParsed.protocol}//${adoParsed.hostname}/${adoParts.slice(0, gitIndex).join('/')}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The frontend constructs Azure DevOps API URLs using the user-provided repoUrl without validating the hostname. This can lead to client-side SSRF and credential leakage if a user is tricked into opening a malicious repository URL, as their PAT will be sent to the attacker's server via fetch.

// Get default branch
let defaultBranchLocal = 'main';
try {
const repoInfoUrl = `${adoBase}/_apis/git/repositories/${adoRepo}?api-version=7.0`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The API version 7.0 is hardcoded here and in a few other places in this function. To improve maintainability, consider defining it as a constant at the top of the file.

// At top of file
const ADO_API_VERSION = '7.0';

// In function
const repoInfoUrl = `${adoBase}/_apis/git/repositories/${adoRepo}?api-version=${ADO_API_VERSION}`;

{t.form?.selectPlatform || 'Select Platform'}
</label>
<div className="flex gap-2">
{(['github', 'gitlab', 'bitbucket', 'azure_devops'] as const).map((platform) => (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The list of supported platforms ['github', 'gitlab', 'bitbucket', 'azure_devops'] is hardcoded. This list is also implicitly used in other components. To improve maintainability and avoid inconsistencies, consider defining this array as a constant in a shared utility file and importing it where needed.

For example:

// in a shared constants file, e.g., src/lib/constants.ts
export const SUPPORTED_PLATFORMS = ['github', 'gitlab', 'bitbucket', 'azure_devops'] as const;

// in ConfigurationModal.tsx
import { SUPPORTED_PLATFORMS } from '@/lib/constants';
// ...
{SUPPORTED_PLATFORMS.map((platform) => (
// ...

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.

Feature Request: Azure DevOps support

1 participant