Coverage for src / mafw / devtools / gitlab / api.py: 100%

33 statements  

« prev     ^ index     » next       coverage.py v7.14.0, created at 2026-06-28 13:34 +0000

1# Copyright 2026 European Union 

2# Author: Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu) 

3# SPDX-License-Identifier: EUPL-1.2 

4""" 

5GitLab API configuration and authentication helpers. 

6 

7:author: Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu) 

8""" 

9 

10from __future__ import annotations 

11 

12import os 

13from dataclasses import dataclass 

14from typing import Literal, MutableMapping 

15 

16 

17@dataclass(frozen=True, slots=True) 

18class GitlabAPIConfiguration: 

19 """Configuration needed to communicate with the GitLab API. 

20 

21 :param api_url: Base GitLab API v4 URL. 

22 :type api_url: str 

23 :param on_ci: Whether the process runs on GitLab CI. 

24 :type on_ci: bool 

25 :param project_id: GitLab project numeric ID. 

26 :type project_id: int 

27 :param token: Authentication token value. 

28 :type token: str 

29 :param token_type: Token kind used for authentication. 

30 :type token_type: Literal['job_token', 'api_token'] 

31 """ 

32 

33 api_url: str 

34 on_ci: bool 

35 project_id: int 

36 token: str 

37 token_type: Literal['job_token', 'api_token'] 

38 

39 

40def build_gitlab_api_configuration( 

41 api_url: str | None, project_id: int | None, token: str | None 

42) -> GitlabAPIConfiguration: 

43 """Build a GitLab API configuration from provided values and environment context. 

44 

45 :param api_url: Optional override for the GitLab API URL. 

46 :type api_url: str | None 

47 :param project_id: Optional override for the GitLab project ID. 

48 :type project_id: int | None 

49 :param token: Optional override for the authentication token. 

50 :type token: str | None 

51 :return: The validated GitLab API configuration. 

52 :rtype: GitlabAPIConfiguration 

53 :raises ValueError: If any required configuration value is missing. 

54 """ 

55 if api_url is None: 

56 api_url = os.environ.get('CI_API_V4_URL') 

57 if project_id is None: 

58 project_id_env = os.environ.get('CI_PROJECT_ID') 

59 project_id = int(project_id_env) if project_id_env else None 

60 if token is None: 

61 token = os.environ.get('CI_JOB_TOKEN') 

62 

63 missing: list[str] = [] 

64 if not api_url: 

65 missing.append('api_url') 

66 if project_id is None: 

67 missing.append('project_id') 

68 if not token: 

69 missing.append('token') 

70 

71 if missing or api_url is None or project_id is None or token is None: 

72 raise ValueError(f'Missing GitLab configuration values: {", ".join(missing)}') 

73 

74 return GitlabAPIConfiguration( 

75 api_url=api_url, 

76 on_ci=bool(os.environ.get('CI')), 

77 project_id=project_id, 

78 token=token, 

79 token_type='job_token' if bool(os.environ.get('CI')) else 'api_token', 

80 ) 

81 

82 

83def build_gitlab_auth_headers(api_config: GitlabAPIConfiguration) -> MutableMapping[str, str | bytes]: 

84 """Build authentication headers for GitLab API requests. 

85 

86 :param api_config: The GitLab API configuration. 

87 :type api_config: GitlabAPIConfiguration 

88 :return: A mutable mapping of HTTP headers. 

89 :rtype: MutableMapping[str, str | bytes] 

90 """ 

91 if api_config.on_ci: 

92 return {'JOB-TOKEN': api_config.token} 

93 return {'PRIVATE-TOKEN': api_config.token}