# Copyright 2026 European Union
# Author: Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu)
# SPDX-License-Identifier: EUPL-1.2
"""
GitLab API configuration and authentication helpers.
:author: Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu)
"""
from __future__ import annotations
import os
from collections.abc import MutableMapping
from dataclasses import dataclass
from typing import Literal
[docs]
@dataclass(frozen=True, slots=True)
class GitlabAPIConfiguration:
"""Configuration needed to communicate with the GitLab API.
:param api_url: Base GitLab API v4 URL.
:type api_url: str
:param on_ci: Whether the process runs on GitLab CI.
:type on_ci: bool
:param project_id: GitLab project numeric ID.
:type project_id: int
:param token: Authentication token value.
:type token: str
:param token_type: Token kind used for authentication.
:type token_type: Literal['job_token', 'api_token']
"""
api_url: str
on_ci: bool
project_id: int
token: str
token_type: Literal['job_token', 'api_token']
[docs]
def build_gitlab_api_configuration(
api_url: str | None, project_id: int | None, token: str | None
) -> GitlabAPIConfiguration:
"""Build a GitLab API configuration from provided values and environment context.
:param api_url: Optional override for the GitLab API URL.
:type api_url: str | None
:param project_id: Optional override for the GitLab project ID.
:type project_id: int | None
:param token: Optional override for the authentication token.
:type token: str | None
:return: The validated GitLab API configuration.
:rtype: gitlab.GitlabAPIConfiguration
:raises ValueError: If any required configuration value is missing.
"""
if api_url is None:
api_url = os.environ.get('CI_API_V4_URL')
if project_id is None:
project_id_env = os.environ.get('CI_PROJECT_ID')
project_id = int(project_id_env) if project_id_env else None
if token is None:
token = os.environ.get('CI_JOB_TOKEN')
missing: list[str] = []
if not api_url:
missing.append('api_url')
if project_id is None:
missing.append('project_id')
if not token:
missing.append('token')
if missing or api_url is None or project_id is None or token is None:
raise ValueError(f'Missing GitLab configuration values: {", ".join(missing)}')
return GitlabAPIConfiguration(
api_url=api_url,
on_ci=bool(os.environ.get('CI')),
project_id=project_id,
token=token,
token_type='job_token' if bool(os.environ.get('CI')) else 'api_token',
)