gitlabform 4.0.4__tar.gz → 4.0.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gitlabform-4.0.4 → gitlabform-4.0.6}/PKG-INFO +22 -11
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/gitlab/__init__.py +9 -4
- gitlabform-4.0.6/gitlabform/gitlab/python_gitlab.py +254 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/group/group_members_processor.py +20 -7
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/project/branches_processor.py +9 -4
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/project/members_processor.py +24 -14
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/project/tags_processor.py +22 -8
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform.egg-info/PKG-INFO +22 -11
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform.egg-info/requires.txt +10 -9
- {gitlabform-4.0.4 → gitlabform-4.0.6}/setup.py +10 -9
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_variables.py +9 -1
- gitlabform-4.0.4/gitlabform/gitlab/python_gitlab.py +0 -111
- {gitlabform-4.0.4 → gitlabform-4.0.6}/LICENSE +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/README.md +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/__init__.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/configuration/__init__.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/configuration/common.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/configuration/core.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/configuration/groups.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/configuration/projects.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/configuration/transform.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/constants.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/gitlab/commits.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/gitlab/core.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/gitlab/group_badges.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/gitlab/group_ldap_links.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/gitlab/group_variables.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/gitlab/groups.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/gitlab/merge_requests.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/gitlab/pipelines.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/gitlab/project_badges.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/gitlab/project_deploy_keys.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/gitlab/project_merge_requests_approvals.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/gitlab/project_protected_environments.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/gitlab/projects.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/gitlab/users.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/gitlab/variables.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/lists/__init__.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/lists/filter.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/lists/groups.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/lists/projects.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/output.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/__init__.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/abstract_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/application/__init__.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/application/application_settings_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/defining_keys.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/group/__init__.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/group/group_badges_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/group/group_labels_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/group/group_ldap_links_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/group/group_saml_links_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/group/group_settings_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/group/group_variables_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/multiple_entities_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/project/__init__.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/project/badges_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/project/deploy_keys_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/project/files_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/project/hooks_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/project/integrations_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/project/job_token_scope_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/project/merge_requests_approval_rules.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/project/merge_requests_approvals.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/project/project_labels_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/project/project_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/project/project_push_rules_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/project/project_settings_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/project/resource_groups_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/project/schedules_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/project/variables_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/shared/__init__.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/shared/protected_environments_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/single_entity_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/util/__init__.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/util/decorators.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/util/difference_logger.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/util/labels_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/run.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/util.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform.egg-info/SOURCES.txt +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform.egg-info/dependency_links.txt +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform.egg-info/entry_points.txt +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform.egg-info/top_level.txt +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/setup.cfg +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/__init__.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/__init__.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/conftest.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/__init__.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_application_settings.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_archive_project.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_badges.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_branches.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_deploy_keys.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_deploy_keys_all_projects.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_files.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_files_templates.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_group_badges.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_group_labels.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_group_members_case_insensitive.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_group_members_groups.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_group_members_users.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_group_settings.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_group_variables.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_hooks.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_integrations.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_job_token_scope.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_members.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_members_add_group.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_members_enforce.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_project_group_members_case_insensitive.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_project_labels.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_project_members_case_insensitve.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_project_settings.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_resource_groups.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_running.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_schedules.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_tags.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_token_from_config.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/acceptance/standard/test_transfer_project.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/unit/__init__.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/unit/configuration/__init__.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/unit/configuration/test_case_sensitivity.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/unit/configuration/test_inheritance_break_projects_and_groups.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/unit/configuration/test_inheritance_break_subgroups.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/unit/configuration/test_inheritance_break_validation.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/unit/configuration/test_projects_and_groups.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/unit/configuration/test_skip_groups_skip_projects.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/unit/configuration/test_subgroups.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/unit/configuration/test_yaml_version.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/unit/processors/__init__.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/unit/processors/test_abstract_processor.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/unit/processors/test_difference_logger.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/unit/processors/test_schedules_processor_extended_cron_pattern.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/unit/test_access_levels.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/unit/test_non_empty_configs_provider.py +0 -0
- {gitlabform-4.0.4 → gitlabform-4.0.6}/tests/unit/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: gitlabform
|
|
3
|
-
Version: 4.0.
|
|
3
|
+
Version: 4.0.6
|
|
4
4
|
Summary: 🏗 Specialized configuration as a code tool for GitLab projects, groups and more using hierarchical configuration written in YAML
|
|
5
5
|
Home-page: https://gitlabform.github.io/gitlabform
|
|
6
6
|
Author: Greg Dubicki and Contributors
|
|
@@ -17,33 +17,44 @@ Classifier: Topic :: Software Development :: Version Control :: Git
|
|
|
17
17
|
Requires-Python: >=3.12.0
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
License-File: LICENSE
|
|
20
|
-
Requires-Dist: certifi==2024.
|
|
21
|
-
Requires-Dist: cli-ui==0.
|
|
20
|
+
Requires-Dist: certifi==2024.12.14
|
|
21
|
+
Requires-Dist: cli-ui==0.18.0
|
|
22
22
|
Requires-Dist: ez-yaml==1.2.0
|
|
23
|
-
Requires-Dist: Jinja2==3.1.
|
|
23
|
+
Requires-Dist: Jinja2==3.1.5
|
|
24
24
|
Requires-Dist: luddite==1.0.4
|
|
25
25
|
Requires-Dist: MarkupSafe==3.0.2
|
|
26
26
|
Requires-Dist: mergedeep==1.3.4
|
|
27
27
|
Requires-Dist: packaging==24.2
|
|
28
|
-
Requires-Dist: python-gitlab==5.
|
|
28
|
+
Requires-Dist: python-gitlab==5.3.0
|
|
29
|
+
Requires-Dist: python-gitlab[graphql]==5.3.0
|
|
29
30
|
Requires-Dist: requests==2.32.3
|
|
30
31
|
Requires-Dist: ruamel.yaml==0.17.21
|
|
31
32
|
Requires-Dist: types-requests==2.32.0.20241016
|
|
32
33
|
Requires-Dist: yamlpath==3.8.2
|
|
33
34
|
Provides-Extra: test
|
|
34
|
-
Requires-Dist: coverage==7.6.
|
|
35
|
-
Requires-Dist: cryptography==
|
|
36
|
-
Requires-Dist: deepdiff==8.
|
|
37
|
-
Requires-Dist: mypy==1.
|
|
35
|
+
Requires-Dist: coverage==7.6.10; extra == "test"
|
|
36
|
+
Requires-Dist: cryptography==44.0.0; extra == "test"
|
|
37
|
+
Requires-Dist: deepdiff==8.1.1; extra == "test"
|
|
38
|
+
Requires-Dist: mypy==1.14.1; extra == "test"
|
|
38
39
|
Requires-Dist: mypy-extensions==1.0.0; extra == "test"
|
|
39
40
|
Requires-Dist: pre-commit==2.21.0; extra == "test"
|
|
40
|
-
Requires-Dist: pytest==8.3.
|
|
41
|
+
Requires-Dist: pytest==8.3.4; extra == "test"
|
|
41
42
|
Requires-Dist: pytest-cov==6.0.0; extra == "test"
|
|
42
43
|
Requires-Dist: pytest-rerunfailures==15.0; extra == "test"
|
|
43
44
|
Requires-Dist: xkcdpass==1.19.9; extra == "test"
|
|
44
45
|
Provides-Extra: docs
|
|
45
46
|
Requires-Dist: mkdocs; extra == "docs"
|
|
46
47
|
Requires-Dist: mkdocs-material; extra == "docs"
|
|
48
|
+
Dynamic: author
|
|
49
|
+
Dynamic: classifier
|
|
50
|
+
Dynamic: description
|
|
51
|
+
Dynamic: description-content-type
|
|
52
|
+
Dynamic: home-page
|
|
53
|
+
Dynamic: keywords
|
|
54
|
+
Dynamic: provides-extra
|
|
55
|
+
Dynamic: requires-dist
|
|
56
|
+
Dynamic: requires-python
|
|
57
|
+
Dynamic: summary
|
|
47
58
|
|
|
48
59
|
[](https://badge.fury.io/gh/gitlabform%2Fgitlabform)
|
|
49
60
|

|
|
@@ -2,6 +2,8 @@ import enum
|
|
|
2
2
|
|
|
3
3
|
from typing import List
|
|
4
4
|
|
|
5
|
+
from gitlab import GraphQL
|
|
6
|
+
|
|
5
7
|
from gitlabform.gitlab.commits import GitLabCommits
|
|
6
8
|
from gitlabform.gitlab.group_badges import GitLabGroupBadges
|
|
7
9
|
from gitlabform.gitlab.group_ldap_links import GitLabGroupLDAPLinks
|
|
@@ -71,14 +73,17 @@ class GitlabWrapper:
|
|
|
71
73
|
timeout = gitlabform.timeout
|
|
72
74
|
session = gitlabform.session
|
|
73
75
|
|
|
76
|
+
graphql = GraphQL(url=url, token=token)
|
|
77
|
+
|
|
74
78
|
self._gitlab: PythonGitlab = PythonGitlab(
|
|
75
|
-
url,
|
|
76
|
-
token,
|
|
79
|
+
url=url,
|
|
80
|
+
private_token=token,
|
|
77
81
|
ssl_verify=ssl_verify,
|
|
82
|
+
timeout=timeout,
|
|
78
83
|
api_version="4",
|
|
79
|
-
session=session,
|
|
80
84
|
retry_transient_errors=True,
|
|
81
|
-
|
|
85
|
+
graphql=graphql,
|
|
86
|
+
session=session,
|
|
82
87
|
)
|
|
83
88
|
|
|
84
89
|
def get_gitlab(self):
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
from typing import Union, Any, Optional, Dict, List
|
|
3
|
+
|
|
4
|
+
import gitlab.const
|
|
5
|
+
from gitlab import Gitlab, GitlabGetError, GraphQL
|
|
6
|
+
from gitlab.base import RESTObject
|
|
7
|
+
from gitlab.v4.objects import Group, Project
|
|
8
|
+
|
|
9
|
+
from cli_ui import debug as verbose
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# Extends the python-gitlab class to add convenience wrappers for common functionality used within gitlabform
|
|
13
|
+
class PythonGitlab(Gitlab):
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
graphql: GraphQL,
|
|
17
|
+
url: Optional[str] = None,
|
|
18
|
+
private_token: Optional[str] = None,
|
|
19
|
+
oauth_token: Optional[str] = None,
|
|
20
|
+
job_token: Optional[str] = None,
|
|
21
|
+
ssl_verify: Union[bool, str] = True,
|
|
22
|
+
http_username: Optional[str] = None,
|
|
23
|
+
http_password: Optional[str] = None,
|
|
24
|
+
timeout: Optional[float] = None,
|
|
25
|
+
api_version: str = "4",
|
|
26
|
+
per_page: Optional[int] = None,
|
|
27
|
+
pagination: Optional[str] = None,
|
|
28
|
+
order_by: Optional[str] = None,
|
|
29
|
+
user_agent: str = gitlab.const.USER_AGENT,
|
|
30
|
+
retry_transient_errors: bool = False,
|
|
31
|
+
keep_base_url: bool = False,
|
|
32
|
+
**kwargs: Any,
|
|
33
|
+
) -> None:
|
|
34
|
+
super().__init__(
|
|
35
|
+
url,
|
|
36
|
+
private_token,
|
|
37
|
+
oauth_token,
|
|
38
|
+
job_token,
|
|
39
|
+
ssl_verify,
|
|
40
|
+
http_username,
|
|
41
|
+
http_password,
|
|
42
|
+
timeout,
|
|
43
|
+
api_version,
|
|
44
|
+
per_page,
|
|
45
|
+
pagination,
|
|
46
|
+
order_by,
|
|
47
|
+
user_agent,
|
|
48
|
+
retry_transient_errors,
|
|
49
|
+
keep_base_url,
|
|
50
|
+
**kwargs,
|
|
51
|
+
)
|
|
52
|
+
# Python Gitlab GraphQL interface
|
|
53
|
+
# https://python-gitlab.readthedocs.io/en/stable/api-usage-graphql.html
|
|
54
|
+
self.graphql = graphql
|
|
55
|
+
|
|
56
|
+
@functools.lru_cache()
|
|
57
|
+
def get_user_id_cached(self, username) -> int:
|
|
58
|
+
user = self._get_user_by_username_cached(username)
|
|
59
|
+
return user.id
|
|
60
|
+
|
|
61
|
+
def get_group_id(self, groupname) -> int:
|
|
62
|
+
group = self.get_group_by_path_cached(groupname)
|
|
63
|
+
return group.id
|
|
64
|
+
|
|
65
|
+
def get_project_id(self, name) -> int:
|
|
66
|
+
project = self.get_project_by_path_cached(name)
|
|
67
|
+
return project.id
|
|
68
|
+
|
|
69
|
+
@functools.lru_cache()
|
|
70
|
+
def get_project_by_path_cached(self, name: str, lazy: bool = False) -> Project:
|
|
71
|
+
project: Project = self.projects.get(name, lazy)
|
|
72
|
+
if project:
|
|
73
|
+
return project
|
|
74
|
+
|
|
75
|
+
raise GitlabGetError("No project found when getting '%s'" % name, 404)
|
|
76
|
+
|
|
77
|
+
@functools.lru_cache()
|
|
78
|
+
def get_group_by_path_cached(self, groupname: str) -> Group:
|
|
79
|
+
group: Group = self.groups.get(groupname)
|
|
80
|
+
if group:
|
|
81
|
+
return group
|
|
82
|
+
|
|
83
|
+
raise GitlabGetError("No group found when getting '%s'" % groupname, 404)
|
|
84
|
+
|
|
85
|
+
# Uses "LIST" to get a user by username, to get the full User object, call get using the user's id
|
|
86
|
+
@functools.lru_cache()
|
|
87
|
+
def _get_user_by_username_cached(self, username: str) -> RESTObject:
|
|
88
|
+
# Gitlab API will only ever return 0 or 1 entry when GETting using `username` attribute
|
|
89
|
+
# https://docs.gitlab.com/ee/api/users.html#for-non-administrator-users
|
|
90
|
+
# so will always be list[RESTObject] and never RESTObjectList from python-gitlab's api
|
|
91
|
+
users: list[RESTObject] = self.users.list(username=username) # type: ignore
|
|
92
|
+
|
|
93
|
+
if len(users) == 0:
|
|
94
|
+
raise GitlabGetError(
|
|
95
|
+
"No users found when searching for username '%s'" % username, 404
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
return users[0]
|
|
99
|
+
|
|
100
|
+
@functools.lru_cache()
|
|
101
|
+
def _get_member_roles_from_group_cached(
|
|
102
|
+
self, group_full_path: str
|
|
103
|
+
) -> List[Dict[str, str]]:
|
|
104
|
+
"""Query GraphQL using Python Gitlab
|
|
105
|
+
https://python-gitlab.readthedocs.io/en/stable/api-usage-graphql.html
|
|
106
|
+
|
|
107
|
+
GET Member_Role via REST Api needs "Owner" on Gitlab.com or "Admin" on Dedicated
|
|
108
|
+
List of custom roles can be retrieved via GraphQL endpoint with "Guest+"
|
|
109
|
+
https://gitlab.com/gitlab-org/gitlab/-/issues/511919#note_2287581884
|
|
110
|
+
|
|
111
|
+
https://docs.gitlab.com/ee/api/graphql/reference/index.html#groupmemberroles
|
|
112
|
+
"""
|
|
113
|
+
|
|
114
|
+
if group_full_path is None:
|
|
115
|
+
raise GitlabGetError(
|
|
116
|
+
"Group Path must be provided when getting member roles",
|
|
117
|
+
404,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
query = (
|
|
121
|
+
"""
|
|
122
|
+
{
|
|
123
|
+
group(fullPath: \""""
|
|
124
|
+
+ group_full_path
|
|
125
|
+
+ """\") {
|
|
126
|
+
memberRoles {
|
|
127
|
+
nodes {
|
|
128
|
+
id
|
|
129
|
+
name
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
"""
|
|
135
|
+
)
|
|
136
|
+
verbose(
|
|
137
|
+
f"Executing graphQl query to get Member Roles for Group '{group_full_path}'"
|
|
138
|
+
)
|
|
139
|
+
result = self.graphql.execute(query)
|
|
140
|
+
|
|
141
|
+
# Validate Group / MemberRoles exist
|
|
142
|
+
if (
|
|
143
|
+
result["group"] is not None
|
|
144
|
+
and result["group"]["memberRoles"] is not None
|
|
145
|
+
and result["group"]["memberRoles"]["nodes"] is not None
|
|
146
|
+
):
|
|
147
|
+
member_role_nodes = result["group"]["memberRoles"]["nodes"]
|
|
148
|
+
else:
|
|
149
|
+
raise GitlabGetError(f"Failed to get Member Roles from Group: {query}")
|
|
150
|
+
|
|
151
|
+
return self._convert_result_to_member_roles(member_role_nodes)
|
|
152
|
+
|
|
153
|
+
@functools.lru_cache()
|
|
154
|
+
def _get_member_roles_from_instance_cached(self) -> List[Dict[str, str]]:
|
|
155
|
+
"""Query GraphQL using Python Gitlab
|
|
156
|
+
https://python-gitlab.readthedocs.io/en/stable/api-usage-graphql.html
|
|
157
|
+
|
|
158
|
+
GET Member_Role via REST Api needs "Admin" on Dedicated/Self-Hosted
|
|
159
|
+
|
|
160
|
+
On Self-Hosted/Dedicated it is only possible to create Member Roles at an instance level, so we query at that
|
|
161
|
+
level and cache the result in order to save API calls when processing multiple Groups
|
|
162
|
+
|
|
163
|
+
List of custom roles can be retrieved via GraphQL endpoint with "Guest+"
|
|
164
|
+
https://gitlab.com/gitlab-org/gitlab/-/issues/511919#note_2287581884
|
|
165
|
+
|
|
166
|
+
https://docs.gitlab.com/ee/api/graphql/reference/index.html#groupmemberroles
|
|
167
|
+
"""
|
|
168
|
+
|
|
169
|
+
query = """
|
|
170
|
+
{
|
|
171
|
+
memberRoles {
|
|
172
|
+
edges {
|
|
173
|
+
node {
|
|
174
|
+
id
|
|
175
|
+
name
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
"""
|
|
181
|
+
result = self.graphql.execute(query)
|
|
182
|
+
|
|
183
|
+
if (
|
|
184
|
+
result["memberRoles"] is not None
|
|
185
|
+
and result["memberRoles"]["edges"] is not None
|
|
186
|
+
):
|
|
187
|
+
member_role_edges = result["memberRoles"]["edges"]
|
|
188
|
+
else:
|
|
189
|
+
raise GitlabGetError(f"Failed to get Member Roles from instance: {query}")
|
|
190
|
+
|
|
191
|
+
member_role_nodes = []
|
|
192
|
+
|
|
193
|
+
for edge in member_role_edges:
|
|
194
|
+
member_role_nodes.append(edge["node"])
|
|
195
|
+
|
|
196
|
+
return self._convert_result_to_member_roles(member_role_nodes)
|
|
197
|
+
|
|
198
|
+
@staticmethod
|
|
199
|
+
def _convert_result_to_member_roles(
|
|
200
|
+
member_role_nodes: List[Dict[str, str]]
|
|
201
|
+
) -> List[Dict[str, str]]:
|
|
202
|
+
# Unwrap Ids from GraphQl Gids
|
|
203
|
+
member_role_id_prefix = "gid://gitlab/MemberRole/"
|
|
204
|
+
|
|
205
|
+
member_roles = []
|
|
206
|
+
for node in member_role_nodes:
|
|
207
|
+
member_role_id = node["id"]
|
|
208
|
+
member_role_id = member_role_id.replace(member_role_id_prefix, "")
|
|
209
|
+
member_roles.append({"id": member_role_id, "name": node["name"]})
|
|
210
|
+
|
|
211
|
+
return member_roles
|
|
212
|
+
|
|
213
|
+
@staticmethod
|
|
214
|
+
def _get_member_role_from_member_roles(
|
|
215
|
+
name_or_id: Union[int, str], member_roles: List[Dict[str, str]]
|
|
216
|
+
) -> Dict[str, str]:
|
|
217
|
+
for member_role in member_roles:
|
|
218
|
+
member_role_id: str = member_role["id"]
|
|
219
|
+
member_role_name: str = member_role["name"]
|
|
220
|
+
if int(member_role_id) == name_or_id:
|
|
221
|
+
return member_role
|
|
222
|
+
elif member_role_name.lower() == str(name_or_id).lower():
|
|
223
|
+
return member_role
|
|
224
|
+
|
|
225
|
+
# Failed to find member role so throw an exception explaining such to user
|
|
226
|
+
raise GitlabGetError(
|
|
227
|
+
f"Member Role with name or id {name_or_id} could not be found",
|
|
228
|
+
404,
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
def get_member_role_id_cached(
|
|
232
|
+
self, name_or_id: Union[int, str], group_full_path: str
|
|
233
|
+
) -> int:
|
|
234
|
+
"""
|
|
235
|
+
GETs a member role id set in the config by the Name of the Member Role (by calling out to API) or by Id
|
|
236
|
+
|
|
237
|
+
Get member_roles calls themselves are Cached, the logic in this method otherwise performs no API calls,
|
|
238
|
+
so we should not cache the result of this specific method, otherwise we may fill the cache with duplicate data
|
|
239
|
+
"""
|
|
240
|
+
if type(name_or_id) is int:
|
|
241
|
+
# Already supplied as an id so no need to go get it from API
|
|
242
|
+
return name_or_id
|
|
243
|
+
|
|
244
|
+
if self._is_gitlab_saas():
|
|
245
|
+
member_roles = self._get_member_roles_from_group_cached(group_full_path)
|
|
246
|
+
else:
|
|
247
|
+
member_roles = self._get_member_roles_from_instance_cached()
|
|
248
|
+
|
|
249
|
+
member_role = self._get_member_role_from_member_roles(name_or_id, member_roles)
|
|
250
|
+
|
|
251
|
+
return int(member_role["id"])
|
|
252
|
+
|
|
253
|
+
def _is_gitlab_saas(self) -> bool:
|
|
254
|
+
return self.url == gitlab.const.DEFAULT_URL
|
{gitlabform-4.0.4 → gitlabform-4.0.6}/gitlabform/processors/group/group_members_processor.py
RENAMED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
from logging import debug, warning
|
|
2
2
|
from typing import Dict, Tuple
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
import gitlab
|
|
5
|
+
from cli_ui import fatal, error
|
|
5
6
|
|
|
6
7
|
from gitlabform.constants import EXIT_INVALID_INPUT
|
|
7
8
|
from gitlabform.gitlab import GitLab, AccessLevel
|
|
@@ -207,13 +208,13 @@ class GroupMembersProcessor(AbstractProcessor):
|
|
|
207
208
|
)
|
|
208
209
|
if member_role_id_or_name:
|
|
209
210
|
member_role_id_to_set = self.gl.get_member_role_id_cached(
|
|
210
|
-
member_role_id_or_name, group.
|
|
211
|
+
member_role_id_or_name, group.full_path
|
|
211
212
|
)
|
|
212
213
|
else:
|
|
213
214
|
member_role_id_to_set = None
|
|
214
215
|
|
|
215
216
|
common_username = user.lower()
|
|
216
|
-
user_id = self.gl.
|
|
217
|
+
user_id = self.gl.get_user_id_cached(user)
|
|
217
218
|
|
|
218
219
|
if common_username in users_before:
|
|
219
220
|
group_member: GroupMember = group.members.get(user_id)
|
|
@@ -273,16 +274,28 @@ class GroupMembersProcessor(AbstractProcessor):
|
|
|
273
274
|
)
|
|
274
275
|
continue
|
|
275
276
|
debug("Removing user '%s' who is not configured to be a member.", user)
|
|
276
|
-
|
|
277
|
+
try:
|
|
278
|
+
user_id = self.gl.get_user_id_cached(user)
|
|
279
|
+
except gitlab.GitlabGetError:
|
|
280
|
+
# User does not exist an instance level but is for whatever reason present on a Group/Project
|
|
281
|
+
# We should raise error into Logs but not prevent the rest of GitLabForm from executing
|
|
282
|
+
# This error is more likely to be prevalent in Dedicated instances; it is unlikely for a User to
|
|
283
|
+
# be completely deleted from gitlab.com
|
|
284
|
+
error(
|
|
285
|
+
f"Could not find User '{user}' on the Instance so can not remove User"
|
|
286
|
+
)
|
|
287
|
+
continue
|
|
288
|
+
|
|
277
289
|
try:
|
|
278
290
|
group.members.delete(user_id)
|
|
279
|
-
except GitlabDeleteError as
|
|
280
|
-
warning(f"Member could not be deleted: "
|
|
291
|
+
except GitlabDeleteError as delete_error:
|
|
292
|
+
warning(f"Member '{user}' could not be deleted: {delete_error}")
|
|
281
293
|
pass
|
|
294
|
+
|
|
282
295
|
else:
|
|
283
296
|
debug("Not enforcing group members.")
|
|
284
297
|
|
|
285
|
-
debug("Group members AFTER:
|
|
298
|
+
debug(f"Group members AFTER: {group.members.list(get_all=True)}")
|
|
286
299
|
|
|
287
300
|
@staticmethod
|
|
288
301
|
def get_group_members(group) -> dict:
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
from logging import debug
|
|
1
2
|
from typing import Optional
|
|
2
|
-
from
|
|
3
|
-
from cli_ui import warning, fatal
|
|
4
|
-
from gitlab.v4.objects import Project, ProjectProtectedBranch
|
|
3
|
+
from cli_ui import warning, fatal, debug as verbose
|
|
5
4
|
from gitlab import (
|
|
6
5
|
GitlabGetError,
|
|
7
6
|
GitlabDeleteError,
|
|
8
7
|
GitlabCreateError,
|
|
9
8
|
)
|
|
9
|
+
from gitlab.v4.objects import Project, ProjectProtectedBranch
|
|
10
|
+
|
|
11
|
+
from gitlabform import gitlab
|
|
10
12
|
from gitlabform.constants import EXIT_INVALID_INPUT, EXIT_PROCESSING_ERROR
|
|
11
13
|
from gitlabform.gitlab import GitLab
|
|
12
14
|
from gitlabform.processors.abstract_processor import AbstractProcessor
|
|
@@ -123,13 +125,16 @@ class BranchesProcessor(AbstractProcessor):
|
|
|
123
125
|
or group name but GitLab only supports their id. This method will transform the
|
|
124
126
|
config by replacing them with ids.
|
|
125
127
|
"""
|
|
128
|
+
verbose("Transforming User and Group names in Branch configuration to Ids")
|
|
126
129
|
|
|
127
130
|
for key in branch_config:
|
|
128
131
|
if isinstance(branch_config[key], list):
|
|
129
132
|
for item in branch_config[key]:
|
|
130
133
|
if isinstance(item, dict):
|
|
131
134
|
if "user" in item:
|
|
132
|
-
item["user_id"] = self.gl.
|
|
135
|
+
item["user_id"] = self.gl.get_user_id_cached(
|
|
136
|
+
item.pop("user")
|
|
137
|
+
)
|
|
133
138
|
elif "group" in item:
|
|
134
139
|
item["group_id"] = self.gl.get_group_id(item.pop("group"))
|
|
135
140
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
from cli_ui import debug as verbose, warning, info
|
|
1
|
+
from cli_ui import debug as verbose, warning, info, error
|
|
2
2
|
from cli_ui import fatal
|
|
3
|
-
from gitlab import GitlabGetError
|
|
3
|
+
from gitlab import GitlabGetError, GitlabDeleteError
|
|
4
4
|
from gitlab.v4.objects import Project
|
|
5
5
|
|
|
6
6
|
from gitlabform.constants import EXIT_INVALID_INPUT
|
|
@@ -113,7 +113,7 @@ class MembersProcessor(AbstractProcessor):
|
|
|
113
113
|
for user in users:
|
|
114
114
|
info(f"Processing user '{user}'...")
|
|
115
115
|
try:
|
|
116
|
-
user_id = self.gl.
|
|
116
|
+
user_id = self.gl.get_user_id_cached(user)
|
|
117
117
|
except GitlabGetError:
|
|
118
118
|
warning(f"Could not find user '{user}' in Gitlab, skipping...")
|
|
119
119
|
continue
|
|
@@ -132,14 +132,9 @@ class MembersProcessor(AbstractProcessor):
|
|
|
132
132
|
users[user]["member_role"] if "member_role" in users[user] else None
|
|
133
133
|
)
|
|
134
134
|
if member_role_id_or_name:
|
|
135
|
-
|
|
136
|
-
if self.gl.is_gitlab_saas():
|
|
137
|
-
group_id = project.namespace["id"]
|
|
138
|
-
else:
|
|
139
|
-
group_id = None
|
|
140
|
-
|
|
135
|
+
group_name_and_path = project.namespace["full_path"]
|
|
141
136
|
member_role_id = self.gl.get_member_role_id_cached(
|
|
142
|
-
member_role_id_or_name,
|
|
137
|
+
member_role_id_or_name, group_name_and_path
|
|
143
138
|
)
|
|
144
139
|
else:
|
|
145
140
|
member_role_id = None
|
|
@@ -222,10 +217,25 @@ class MembersProcessor(AbstractProcessor):
|
|
|
222
217
|
verbose(
|
|
223
218
|
f"Removing user '{user_not_in_config}' that is not configured to be a member."
|
|
224
219
|
)
|
|
225
|
-
|
|
226
|
-
user_not_in_config
|
|
227
|
-
|
|
228
|
-
|
|
220
|
+
try:
|
|
221
|
+
user_id = self.gl.get_user_id_cached(user_not_in_config)
|
|
222
|
+
except GitlabGetError:
|
|
223
|
+
# User does not exist an instance level but is for whatever reason present on a Group/Project
|
|
224
|
+
# We should raise error into Logs but not prevent the rest of GitLabForm from executing
|
|
225
|
+
# This error is more likely to be prevalent in Dedicated instances; it is unlikely for a User to
|
|
226
|
+
# be completely deleted from gitlab.com
|
|
227
|
+
warning(
|
|
228
|
+
f"Could not find User '{user_not_in_config}' on the Instance so can not remove User from Project '{project_and_group}'"
|
|
229
|
+
)
|
|
230
|
+
continue
|
|
231
|
+
|
|
232
|
+
try:
|
|
233
|
+
project.members.delete(id=user_id)
|
|
234
|
+
except GitlabDeleteError as delete_error:
|
|
235
|
+
error(
|
|
236
|
+
f"Member '{user_not_in_config}' could not be deleted: {delete_error}"
|
|
237
|
+
)
|
|
238
|
+
raise delete_error
|
|
229
239
|
else:
|
|
230
240
|
verbose("Not enforcing user members.")
|
|
231
241
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from logging import debug
|
|
2
|
-
from cli_ui import warning, fatal
|
|
2
|
+
from cli_ui import warning, fatal, error
|
|
3
3
|
|
|
4
4
|
from gitlabform.constants import EXIT_PROCESSING_ERROR
|
|
5
5
|
from gitlabform.gitlab import GitLab
|
|
@@ -35,16 +35,30 @@ class TagsProcessor(AbstractProcessor):
|
|
|
35
35
|
elif "user_id" in config:
|
|
36
36
|
user_ids.add(config["user_id"])
|
|
37
37
|
elif "user" in config:
|
|
38
|
-
|
|
39
|
-
config["user"]
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
try:
|
|
39
|
+
user_id = self.gl.get_user_id_cached(config["user"])
|
|
40
|
+
except GitlabGetError as e:
|
|
41
|
+
error(
|
|
42
|
+
f"Could not find User '{config["user"]}' on the Instance, cannot Protect "
|
|
43
|
+
f"Tag with them"
|
|
44
|
+
)
|
|
45
|
+
raise e
|
|
46
|
+
|
|
47
|
+
user_ids.add(user_id)
|
|
42
48
|
elif "group_id" in config:
|
|
43
49
|
group_ids.add(config["group_id"])
|
|
44
50
|
elif "group" in config:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
51
|
+
try:
|
|
52
|
+
gitlab_group = self.gl.get_group_by_path_cached(
|
|
53
|
+
config["group"]
|
|
54
|
+
)
|
|
55
|
+
except GitlabGetError as e:
|
|
56
|
+
error(
|
|
57
|
+
f"Could not find Group '{config["group"]}' on the Instance, cannot Protect "
|
|
58
|
+
f"Tag with them"
|
|
59
|
+
)
|
|
60
|
+
raise e
|
|
61
|
+
|
|
48
62
|
group_ids.add(gitlab_group.get_id())
|
|
49
63
|
|
|
50
64
|
for val in access_levels:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: gitlabform
|
|
3
|
-
Version: 4.0.
|
|
3
|
+
Version: 4.0.6
|
|
4
4
|
Summary: 🏗 Specialized configuration as a code tool for GitLab projects, groups and more using hierarchical configuration written in YAML
|
|
5
5
|
Home-page: https://gitlabform.github.io/gitlabform
|
|
6
6
|
Author: Greg Dubicki and Contributors
|
|
@@ -17,33 +17,44 @@ Classifier: Topic :: Software Development :: Version Control :: Git
|
|
|
17
17
|
Requires-Python: >=3.12.0
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
License-File: LICENSE
|
|
20
|
-
Requires-Dist: certifi==2024.
|
|
21
|
-
Requires-Dist: cli-ui==0.
|
|
20
|
+
Requires-Dist: certifi==2024.12.14
|
|
21
|
+
Requires-Dist: cli-ui==0.18.0
|
|
22
22
|
Requires-Dist: ez-yaml==1.2.0
|
|
23
|
-
Requires-Dist: Jinja2==3.1.
|
|
23
|
+
Requires-Dist: Jinja2==3.1.5
|
|
24
24
|
Requires-Dist: luddite==1.0.4
|
|
25
25
|
Requires-Dist: MarkupSafe==3.0.2
|
|
26
26
|
Requires-Dist: mergedeep==1.3.4
|
|
27
27
|
Requires-Dist: packaging==24.2
|
|
28
|
-
Requires-Dist: python-gitlab==5.
|
|
28
|
+
Requires-Dist: python-gitlab==5.3.0
|
|
29
|
+
Requires-Dist: python-gitlab[graphql]==5.3.0
|
|
29
30
|
Requires-Dist: requests==2.32.3
|
|
30
31
|
Requires-Dist: ruamel.yaml==0.17.21
|
|
31
32
|
Requires-Dist: types-requests==2.32.0.20241016
|
|
32
33
|
Requires-Dist: yamlpath==3.8.2
|
|
33
34
|
Provides-Extra: test
|
|
34
|
-
Requires-Dist: coverage==7.6.
|
|
35
|
-
Requires-Dist: cryptography==
|
|
36
|
-
Requires-Dist: deepdiff==8.
|
|
37
|
-
Requires-Dist: mypy==1.
|
|
35
|
+
Requires-Dist: coverage==7.6.10; extra == "test"
|
|
36
|
+
Requires-Dist: cryptography==44.0.0; extra == "test"
|
|
37
|
+
Requires-Dist: deepdiff==8.1.1; extra == "test"
|
|
38
|
+
Requires-Dist: mypy==1.14.1; extra == "test"
|
|
38
39
|
Requires-Dist: mypy-extensions==1.0.0; extra == "test"
|
|
39
40
|
Requires-Dist: pre-commit==2.21.0; extra == "test"
|
|
40
|
-
Requires-Dist: pytest==8.3.
|
|
41
|
+
Requires-Dist: pytest==8.3.4; extra == "test"
|
|
41
42
|
Requires-Dist: pytest-cov==6.0.0; extra == "test"
|
|
42
43
|
Requires-Dist: pytest-rerunfailures==15.0; extra == "test"
|
|
43
44
|
Requires-Dist: xkcdpass==1.19.9; extra == "test"
|
|
44
45
|
Provides-Extra: docs
|
|
45
46
|
Requires-Dist: mkdocs; extra == "docs"
|
|
46
47
|
Requires-Dist: mkdocs-material; extra == "docs"
|
|
48
|
+
Dynamic: author
|
|
49
|
+
Dynamic: classifier
|
|
50
|
+
Dynamic: description
|
|
51
|
+
Dynamic: description-content-type
|
|
52
|
+
Dynamic: home-page
|
|
53
|
+
Dynamic: keywords
|
|
54
|
+
Dynamic: provides-extra
|
|
55
|
+
Dynamic: requires-dist
|
|
56
|
+
Dynamic: requires-python
|
|
57
|
+
Dynamic: summary
|
|
47
58
|
|
|
48
59
|
[](https://badge.fury.io/gh/gitlabform%2Fgitlabform)
|
|
49
60
|

|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
certifi==2024.
|
|
2
|
-
cli-ui==0.
|
|
1
|
+
certifi==2024.12.14
|
|
2
|
+
cli-ui==0.18.0
|
|
3
3
|
ez-yaml==1.2.0
|
|
4
|
-
Jinja2==3.1.
|
|
4
|
+
Jinja2==3.1.5
|
|
5
5
|
luddite==1.0.4
|
|
6
6
|
MarkupSafe==3.0.2
|
|
7
7
|
mergedeep==1.3.4
|
|
8
8
|
packaging==24.2
|
|
9
|
-
python-gitlab==5.
|
|
9
|
+
python-gitlab==5.3.0
|
|
10
|
+
python-gitlab[graphql]==5.3.0
|
|
10
11
|
requests==2.32.3
|
|
11
12
|
ruamel.yaml==0.17.21
|
|
12
13
|
types-requests==2.32.0.20241016
|
|
@@ -17,13 +18,13 @@ mkdocs
|
|
|
17
18
|
mkdocs-material
|
|
18
19
|
|
|
19
20
|
[test]
|
|
20
|
-
coverage==7.6.
|
|
21
|
-
cryptography==
|
|
22
|
-
deepdiff==8.
|
|
23
|
-
mypy==1.
|
|
21
|
+
coverage==7.6.10
|
|
22
|
+
cryptography==44.0.0
|
|
23
|
+
deepdiff==8.1.1
|
|
24
|
+
mypy==1.14.1
|
|
24
25
|
mypy-extensions==1.0.0
|
|
25
26
|
pre-commit==2.21.0
|
|
26
|
-
pytest==8.3.
|
|
27
|
+
pytest==8.3.4
|
|
27
28
|
pytest-cov==6.0.0
|
|
28
29
|
pytest-rerunfailures==15.0
|
|
29
30
|
xkcdpass==1.19.9
|