Source code for sonarqube.api.projects

"""Projects API for SonarQube SDK.

This module provides methods to manage SonarQube projects including
creating, searching, updating, and deleting projects.

Example:
    Using the Projects API::

        from sonarqube import SonarQubeClient

        client = SonarQubeClient(base_url="...", token="...")

        # Search for projects
        projects = client.projects.search(q="backend")
        for project in projects.components:
            print(project.name)

        # Create a project
        project = client.projects.create(name="My Project", project="my-project")
"""

from __future__ import annotations

from typing import Any, Optional

from sonarqube.api.base import BaseAPI
from sonarqube.models.projects import (
    ExportFindingsResponse,
    LicenseUsageResponse,
    ProjectCreateResponse,
    ProjectSearchResponse,
)


[docs] class ProjectsAPI(BaseAPI): """API for managing SonarQube projects. Projects are the main organizational unit in SonarQube. This API provides methods to create, search, update, and delete projects. Attributes: API_PATH: Base path for projects API ("/api/projects"). Example: Using the projects API:: # Search for projects projects = client.projects.search(q="backend") # Create a project project = client.projects.create(name="My Project", project="my-project") # Delete a project client.projects.delete(project="my-project") """ API_PATH = "/api/projects"
[docs] def bulk_delete( self, analyzed_before: Optional[str] = None, on_provisioned_only: Optional[bool] = None, projects: Optional[list[str]] = None, q: Optional[str] = None, qualifiers: Optional[list[str]] = None, visibility: Optional[str] = None, ) -> None: """Delete multiple projects at once. Requires 'Administer System' permission. At most 1000 projects can be deleted per request. Args: analyzed_before: Filter projects analyzed before this date (ISO format). on_provisioned_only: Filter on provisioned projects only. projects: Comma-separated list of project keys to delete. q: Search query for project names or keys. qualifiers: Filter by component qualifiers (TRK, VW, APP). visibility: Filter by visibility (public/private). Raises: SonarQubeValidationError: If validation fails. SonarQubePermissionError: If lacking required permissions. Example: >>> client.projects.bulk_delete(projects=["project1", "project2"]) """ data: dict[str, Any] = {} if analyzed_before: data["analyzedBefore"] = analyzed_before if on_provisioned_only is not None: data["onProvisionedOnly"] = str(on_provisioned_only).lower() if projects: data["projects"] = ",".join(projects) if q: data["q"] = q if qualifiers: data["qualifiers"] = ",".join(qualifiers) if visibility: data["visibility"] = visibility self._post("/bulk_delete", data=data)
[docs] def create( self, name: str, project: str, main_branch: Optional[str] = None, new_code_definition_type: Optional[str] = None, new_code_definition_value: Optional[str] = None, visibility: Optional[str] = None, ) -> ProjectCreateResponse: """Create a new project. Requires 'Create Projects' permission. Args: name: Project name (max 500 characters). project: Project key (unique identifier). main_branch: Main branch name (defaults to 'main'). new_code_definition_type: Type for new code definition. new_code_definition_value: Value for new code definition. visibility: Project visibility (public/private). Returns: Response containing the created project. Raises: SonarQubeValidationError: If validation fails. SonarQubePermissionError: If lacking required permissions. Example: >>> project = client.projects.create( ... name="My Project", project="my-project", visibility="private" ... ) >>> print(project.project.key) 'my-project' """ return self._post_model( "/create", ProjectCreateResponse, data={ "name": name, "project": project, "mainBranch": main_branch, "newCodeDefinitionType": new_code_definition_type, "newCodeDefinitionValue": new_code_definition_value, "visibility": visibility, }, )
[docs] def delete(self, project: str) -> None: """Delete a project. Requires 'Administer System' permission or 'Administer' on the project. Args: project: Project key. Raises: SonarQubeNotFoundError: If project not found. SonarQubePermissionError: If lacking required permissions. Example: >>> client.projects.delete(project="my-project") """ self._post("/delete", data={"project": project})
[docs] def export_findings( self, project: str, branch: Optional[str] = None, pull_request: Optional[str] = None, ) -> ExportFindingsResponse: """Export all findings for a project. Requires 'Browse' permission on the project. Args: project: Project key. branch: Branch name. pull_request: Pull request ID. Returns: Response containing exported findings. Example: >>> findings = client.projects.export_findings(project="my-project") """ return self._get_model( "/export_findings", ExportFindingsResponse, params={ "project": project, "branch": branch, "pullRequest": pull_request, }, )
[docs] def license_usage(self) -> LicenseUsageResponse: """Get license usage statistics. Requires 'Administer System' permission. Returns: Response containing license usage information. Example: >>> usage = client.projects.license_usage() >>> print(f"Total lines of code: {usage.lines_of_code}") """ return self._get_model("/license_usage", LicenseUsageResponse)
[docs] def search( self, analyzed_before: Optional[str] = None, on_provisioned_only: Optional[bool] = None, p: Optional[int] = None, projects: Optional[list[str]] = None, ps: Optional[int] = None, q: Optional[str] = None, qualifiers: Optional[list[str]] = None, s: Optional[str] = None, visibility: Optional[str] = None, ) -> ProjectSearchResponse: """Search for projects. Requires 'Browse' permission on each returned project. Args: analyzed_before: Filter projects analyzed before this date. on_provisioned_only: Filter on provisioned projects only. p: Page number (1-based). projects: Comma-separated list of project keys. ps: Page size (max 500). q: Search query for project names or keys. qualifiers: Filter by component qualifiers. s: Sort field (key, name, qualifier, visibility). visibility: Filter by visibility. Returns: Response containing list of projects and paging info. Example: >>> response = client.projects.search(q="backend") >>> for project in response.components: ... print(project.name) """ params: dict[str, Any] = {} if analyzed_before: params["analyzedBefore"] = analyzed_before if on_provisioned_only is not None: params["onProvisionedOnly"] = str(on_provisioned_only).lower() if p: params["p"] = p if projects: params["projects"] = ",".join(projects) if ps: params["ps"] = ps if q: params["q"] = q if qualifiers: params["qualifiers"] = ",".join(qualifiers) if s: params["s"] = s if visibility: params["visibility"] = visibility return self._get_model("/search", ProjectSearchResponse, params=params)
[docs] def update_key(self, from_key: str, to_key: str) -> None: """Update a project's key. Requires 'Administer' permission on the project. Args: from_key: Current project key. to_key: New project key. Raises: SonarQubeNotFoundError: If project not found. SonarQubeValidationError: If new key is invalid. SonarQubePermissionError: If lacking required permissions. Example: >>> client.projects.update_key(from_key="old-project-key", to_key="new-project-key") """ self._post( "/update_key", data={ "from": from_key, "to": to_key, }, )
[docs] def update_visibility(self, project: str, visibility: str) -> None: """Update a project's visibility. Requires 'Administer' permission on the project. Args: project: Project key. visibility: New visibility (public/private). Raises: SonarQubeNotFoundError: If project not found. SonarQubePermissionError: If lacking required permissions. Example: >>> client.projects.update_visibility(project="my-project", visibility="private") """ self._post( "/update_visibility", data={ "project": project, "visibility": visibility, }, )