Skip to content

client

appimage_updater.repositories.gitlab.client

GitLab API client for AppImage Updater.

This module provides a GitLab API v4 client for fetching release information, supporting both gitlab.com and self-hosted GitLab instances.

GitLabClient(timeout=30, user_agent=None, auth=None)

GitLab API v4 client for release information.

Supports: - GitLab.com and self-hosted GitLab instances - Personal access token authentication - Release and project information fetching - Rate limiting and error handling

Parameters:

Name Type Description Default
timeout int

Request timeout in seconds

30
user_agent str | None

Custom user agent string

None
auth GitLabAuth | None

GitLabAuth instance for authentication

None
Source code in src/appimage_updater/repositories/gitlab/client.py
def __init__(
    self,
    timeout: int = 30,
    user_agent: str | None = None,
    auth: GitLabAuth | None = None,
) -> None:
    """Initialize GitLab API client.

    Args:
        timeout: Request timeout in seconds
        user_agent: Custom user agent string
        auth: GitLabAuth instance for authentication
    """
    self.timeout = timeout
    self.user_agent = user_agent or self._get_default_user_agent()
    self.auth = auth or GitLabAuth()

    # Create HTTP client with default configuration
    self._client = httpx.AsyncClient(
        timeout=timeout, headers={"User-Agent": self.user_agent, **self.auth.get_headers()}
    )

    logger.debug(f"GitLab client initialized with timeout={timeout}s, auth={self.auth.is_authenticated()}")

auth = auth or GitLabAuth() instance-attribute

timeout = timeout instance-attribute

user_agent = user_agent or self._get_default_user_agent() instance-attribute

get_latest_release(owner, repo, base_url='https://gitlab.com') async

Get the latest release for a GitLab project.

Parameters:

Name Type Description Default
owner str

Project owner/namespace

required
repo str

Repository name

required
base_url str

GitLab instance base URL

'https://gitlab.com'

Returns:

Type Description
dict[str, Any]

Latest release information dictionary

Raises:

Type Description
GitLabClientError

If the API request fails or no releases found

Source code in src/appimage_updater/repositories/gitlab/client.py
async def get_latest_release(self, owner: str, repo: str, base_url: str = "https://gitlab.com") -> dict[str, Any]:
    """Get the latest release for a GitLab project.

    Args:
        owner: Project owner/namespace
        repo: Repository name
        base_url: GitLab instance base URL

    Returns:
        Latest release information dictionary

    Raises:
        GitLabClientError: If the API request fails or no releases found
    """
    project_path = self._url_encode_project_path(owner, repo)
    api_url = f"{base_url}/api/v4/projects/{project_path}/releases/permalink/latest"

    try:
        logger.debug(f"Fetching latest GitLab release: {api_url}")
        response = await self._client.get(api_url)
        response.raise_for_status()

        release_info: dict[str, Any] = response.json()
        logger.debug(f"Retrieved latest release {release_info.get('tag_name')} for {owner}/{repo}")
        return release_info

    except httpx.HTTPStatusError as e:
        self._handle_http_status_error(e, owner, repo)
    except httpx.RequestError as e:
        raise GitLabClientError(f"GitLab API request failed: {e}") from e

get_releases(owner, repo, base_url='https://gitlab.com', limit=10) async

Get recent releases for a GitLab project.

Parameters:

Name Type Description Default
owner str

Project owner/namespace

required
repo str

Repository name

required
base_url str

GitLab instance base URL

'https://gitlab.com'
limit int

Maximum number of releases to fetch

10

Returns:

Type Description
list[dict[str, Any]]

List of release information dictionaries

Raises:

Type Description
GitLabClientError

If the API request fails

Source code in src/appimage_updater/repositories/gitlab/client.py
async def get_releases(
    self, owner: str, repo: str, base_url: str = "https://gitlab.com", limit: int = 10
) -> list[dict[str, Any]]:
    """Get recent releases for a GitLab project.

    Args:
        owner: Project owner/namespace
        repo: Repository name
        base_url: GitLab instance base URL
        limit: Maximum number of releases to fetch

    Returns:
        List of release information dictionaries

    Raises:
        GitLabClientError: If the API request fails
    """
    project_path = self._url_encode_project_path(owner, repo)
    api_url = f"{base_url}/api/v4/projects/{project_path}/releases"
    params = self._build_releases_params(limit)

    try:
        logger.debug(f"Fetching GitLab releases: {api_url} (limit={limit})")
        response = await self._client.get(api_url, params=params)
        response.raise_for_status()

        releases: list[dict[str, Any]] = response.json()
        logger.debug(f"Retrieved {len(releases)} releases for {owner}/{repo}")
        return releases[:limit]  # Ensure we don't exceed requested limit

    except httpx.HTTPStatusError as e:
        return self._handle_get_releases_error(e, owner, repo)
    except httpx.RequestError as e:
        raise GitLabClientError(f"GitLab API request failed: {e}") from e

should_enable_prerelease(owner, repo, base_url='https://gitlab.com') async

Check if prerelease should be automatically enabled for a repository.

This method examines recent releases to determine if only prereleases exist. If no stable releases are found in the recent history, it suggests enabling prerelease mode.

Parameters:

Name Type Description Default
owner str

Project owner/namespace

required
repo str

Repository name

required
base_url str

GitLab instance base URL

'https://gitlab.com'

Returns:

Type Description
bool

True if only prereleases are found, False if stable releases exist

Raises:

Type Description
GitLabClientError

If the API request fails

Source code in src/appimage_updater/repositories/gitlab/client.py
async def should_enable_prerelease(self, owner: str, repo: str, base_url: str = "https://gitlab.com") -> bool:
    """Check if prerelease should be automatically enabled for a repository.

    This method examines recent releases to determine if only prereleases exist.
    If no stable releases are found in the recent history, it suggests enabling
    prerelease mode.

    Args:
        owner: Project owner/namespace
        repo: Repository name
        base_url: GitLab instance base URL

    Returns:
        True if only prereleases are found, False if stable releases exist

    Raises:
        GitLabClientError: If the API request fails
    """
    try:
        releases = await self.get_releases(owner, repo, base_url, limit=20)

        if not releases:
            logger.debug(f"No releases found for {owner}/{repo}, prerelease detection inconclusive")
            return False

        stable_count, prerelease_count = self._count_release_types(releases)
        should_enable = prerelease_count > 0 and stable_count == 0

        logger.debug(
            f"Prerelease analysis for {owner}/{repo}: "
            f"stable={stable_count}, prerelease={prerelease_count}, "
            f"should_enable={should_enable}"
        )

        return should_enable

    except GitLabClientError:
        logger.debug(f"Could not analyze releases for {owner}/{repo}, defaulting prerelease=False")
        return False

GitLabClientError

Exception raised for GitLab API client errors.