gitlabform 4.7.0__tar.gz → 5.0.0__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.7.0 → gitlabform-5.0.0}/PKG-INFO +10 -10
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/__init__.py +2 -4
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/configuration/__init__.py +0 -1
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/configuration/core.py +4 -4
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/configuration/transform.py +0 -94
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/gitlab/__init__.py +0 -6
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/gitlab/core.py +40 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/gitlab/projects.py +0 -6
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/lists/filter.py +0 -1
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/abstract_processor.py +2 -4
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/group/group_saml_links_processor.py +5 -4
- gitlabform-5.0.0/gitlabform/processors/group/group_variables_processor.py +26 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/project/__init__.py +2 -2
- gitlabform-5.0.0/gitlabform/processors/project/branches_processor.py +438 -0
- gitlabform-5.0.0/gitlabform/processors/project/project_security_settings.py +68 -0
- gitlabform-5.0.0/gitlabform/processors/project/project_variables_processor.py +95 -0
- gitlabform-5.0.0/gitlabform/processors/util/variables_processor.py +144 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform.egg-info/PKG-INFO +10 -10
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform.egg-info/SOURCES.txt +3 -4
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform.egg-info/requires.txt +8 -8
- {gitlabform-4.7.0 → gitlabform-5.0.0}/pyproject.toml +10 -10
- gitlabform-4.7.0/gitlabform/gitlab/group_variables.py +0 -51
- gitlabform-4.7.0/gitlabform/gitlab/project_security_settings.py +0 -22
- gitlabform-4.7.0/gitlabform/processors/group/group_variables_processor.py +0 -17
- gitlabform-4.7.0/gitlabform/processors/project/branches_processor.py +0 -141
- gitlabform-4.7.0/gitlabform/processors/project/project_security_settings.py +0 -12
- gitlabform-4.7.0/gitlabform/processors/project/variables_processor.py +0 -70
- {gitlabform-4.7.0 → gitlabform-5.0.0}/LICENSE +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/README.md +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/configuration/common.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/configuration/groups.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/configuration/projects.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/constants.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/gitlab/commits.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/gitlab/group_badges.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/gitlab/group_ldap_links.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/gitlab/groups.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/gitlab/merge_requests.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/gitlab/pipelines.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/gitlab/project_badges.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/gitlab/project_deploy_keys.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/gitlab/project_merge_requests_approvals.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/gitlab/project_protected_environments.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/gitlab/python_gitlab.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/gitlab/variables.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/lists/__init__.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/lists/groups.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/lists/projects.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/output.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/__init__.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/application/__init__.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/application/application_settings_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/defining_keys.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/group/__init__.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/group/group_badges_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/group/group_hooks_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/group/group_labels_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/group/group_ldap_links_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/group/group_members_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/group/group_push_rules_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/group/group_settings_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/multiple_entities_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/project/badges_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/project/deploy_keys_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/project/files_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/project/hooks_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/project/integrations_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/project/job_token_scope_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/project/members_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/project/merge_requests_approval_rules.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/project/merge_requests_approvals.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/project/project_labels_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/project/project_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/project/project_push_rules_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/project/project_settings_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/project/remote_mirrors_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/project/resource_groups_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/project/schedules_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/project/tags_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/shared/__init__.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/shared/protected_environments_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/single_entity_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/util/__init__.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/util/decorators.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/util/difference_logger.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/util/labels_processor.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/run.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/util.py +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform.egg-info/dependency_links.txt +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform.egg-info/entry_points.txt +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform.egg-info/top_level.txt +0 -0
- {gitlabform-4.7.0 → gitlabform-5.0.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gitlabform
|
|
3
|
-
Version:
|
|
3
|
+
Version: 5.0.0
|
|
4
4
|
Summary: 🏗 Specialized configuration as a code tool for GitLab projects, groups and more using hierarchical configuration written in YAML
|
|
5
5
|
Author: Greg Dubicki and Contributors
|
|
6
6
|
Project-URL: Homepage, https://gitlabform.github.io/gitlabform/
|
|
@@ -8,7 +8,7 @@ Project-URL: Repository, https://github.com/gitlabform/gitlabform.git
|
|
|
8
8
|
Project-URL: Issues, https://github.com/gitlabform/gitlabform/issues
|
|
9
9
|
Project-URL: Changelog, https://gitlabform.github.io/gitlabform/changelog/
|
|
10
10
|
Keywords: cli,yaml,gitlab,configuration-as-code
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
12
12
|
Classifier: Development Status :: 5 - Production/Stable
|
|
13
13
|
Classifier: Intended Audience :: Information Technology
|
|
14
14
|
Classifier: Intended Audience :: System Administrators
|
|
@@ -20,24 +20,22 @@ Classifier: Topic :: Software Development :: Version Control :: Git
|
|
|
20
20
|
Requires-Python: >=3.12.0
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
22
|
License-File: LICENSE
|
|
23
|
-
Requires-Dist: certifi==2026.
|
|
23
|
+
Requires-Dist: certifi==2026.2.25
|
|
24
24
|
Requires-Dist: cli-ui==0.19.0
|
|
25
25
|
Requires-Dist: ez-yaml==1.2.0
|
|
26
26
|
Requires-Dist: Jinja2==3.1.6
|
|
27
27
|
Requires-Dist: luddite==1.0.4
|
|
28
28
|
Requires-Dist: MarkupSafe==3.0.3
|
|
29
29
|
Requires-Dist: mergedeep==1.3.4
|
|
30
|
-
Requires-Dist: packaging==
|
|
31
|
-
Requires-Dist: python-gitlab==
|
|
32
|
-
Requires-Dist: python-gitlab[graphql]==
|
|
30
|
+
Requires-Dist: packaging==26.0
|
|
31
|
+
Requires-Dist: python-gitlab==8.0.0
|
|
32
|
+
Requires-Dist: python-gitlab[graphql]==8.0.0
|
|
33
33
|
Requires-Dist: requests==2.32.5
|
|
34
34
|
Requires-Dist: ruamel.yaml==0.17.21
|
|
35
|
-
Requires-Dist: types-requests==2.32.4.20260107
|
|
36
|
-
Requires-Dist: types-setuptools==80.9.0.20251223
|
|
37
35
|
Requires-Dist: yamlpath==3.8.2
|
|
38
36
|
Provides-Extra: test
|
|
39
|
-
Requires-Dist: coverage==7.13.
|
|
40
|
-
Requires-Dist: cryptography==46.0.
|
|
37
|
+
Requires-Dist: coverage==7.13.4; extra == "test"
|
|
38
|
+
Requires-Dist: cryptography==46.0.5; extra == "test"
|
|
41
39
|
Requires-Dist: deepdiff==8.6.1; extra == "test"
|
|
42
40
|
Requires-Dist: mypy==1.19.1; extra == "test"
|
|
43
41
|
Requires-Dist: mypy-extensions==1.1.0; extra == "test"
|
|
@@ -45,6 +43,8 @@ Requires-Dist: pre-commit==2.21.0; extra == "test"
|
|
|
45
43
|
Requires-Dist: pytest==9.0.2; extra == "test"
|
|
46
44
|
Requires-Dist: pytest-cov==7.0.0; extra == "test"
|
|
47
45
|
Requires-Dist: pytest-rerunfailures==16.1; extra == "test"
|
|
46
|
+
Requires-Dist: types-requests==2.32.4.20260107; extra == "test"
|
|
47
|
+
Requires-Dist: types-setuptools==82.0.0.20260210; extra == "test"
|
|
48
48
|
Requires-Dist: xkcdpass==1.30.0; extra == "test"
|
|
49
49
|
Provides-Extra: docs
|
|
50
50
|
Requires-Dist: mkdocs; extra == "docs"
|
|
@@ -143,8 +143,7 @@ class GitLabForm:
|
|
|
143
143
|
:return: a tuple with all the arguments that have been parsed
|
|
144
144
|
"""
|
|
145
145
|
parser = argparse.ArgumentParser(
|
|
146
|
-
description=textwrap.dedent(
|
|
147
|
-
f"""
|
|
146
|
+
description=textwrap.dedent(f"""
|
|
148
147
|
🏗 Specialized configuration as a code tool for GitLab projects, groups and more
|
|
149
148
|
using hierarchical configuration written in YAML.
|
|
150
149
|
|
|
@@ -152,8 +151,7 @@ class GitLabForm:
|
|
|
152
151
|
* 0 - on success,
|
|
153
152
|
* {EXIT_INVALID_INPUT} - on invalid input errors (f.e. bad syntax in the config file) ~ "it's your fault". 😅
|
|
154
153
|
* {EXIT_PROCESSING_ERROR} - if there were backend processing errors (f.e. when requests to GitLab fail) ~ "it's not your fault". 😎
|
|
155
|
-
"""
|
|
156
|
-
),
|
|
154
|
+
"""),
|
|
157
155
|
formatter_class=Formatter,
|
|
158
156
|
)
|
|
159
157
|
|
|
@@ -2,7 +2,6 @@ from gitlabform.configuration.common import ConfigurationCommon
|
|
|
2
2
|
from gitlabform.configuration.groups import ConfigurationGroups
|
|
3
3
|
from gitlabform.configuration.projects import ConfigurationProjects
|
|
4
4
|
|
|
5
|
-
|
|
6
5
|
#
|
|
7
6
|
# This the only external interface for operating on the configuration from a given YAML file
|
|
8
7
|
# (or an input string in case of tests).
|
|
@@ -52,9 +52,9 @@ class ConfigurationCore(ABC):
|
|
|
52
52
|
exit_code=EXIT_INVALID_INPUT,
|
|
53
53
|
)
|
|
54
54
|
|
|
55
|
-
if self.config.get("config_version", 1) !=
|
|
55
|
+
if self.config.get("config_version", 1) != 4:
|
|
56
56
|
fatal(
|
|
57
|
-
"This version of GitLabForm requires 'config_version:
|
|
57
|
+
"This version of GitLabForm requires 'config_version: 4' entry in the config. "
|
|
58
58
|
"This ensures that if the application behavior changes in a backward-incompatible way,"
|
|
59
59
|
" you won't apply unwanted configuration to your GitLab instance.\n"
|
|
60
60
|
"Please follow this guide: https://gitlabform.github.io/gitlabform/upgrade/\n",
|
|
@@ -101,11 +101,11 @@ class ConfigurationCore(ABC):
|
|
|
101
101
|
if config_string:
|
|
102
102
|
config = textwrap.dedent(source)
|
|
103
103
|
verbose("Reading config from the provided string.")
|
|
104
|
-
|
|
104
|
+
yaml_data, doc_loaded = Parsers.get_yaml_data(yaml, log, config, literal=True)
|
|
105
105
|
else:
|
|
106
106
|
config_path = source
|
|
107
107
|
verbose(f"Reading config from file: {config_path}")
|
|
108
|
-
|
|
108
|
+
yaml_data, doc_loaded = Parsers.get_yaml_data(yaml, log, config_path)
|
|
109
109
|
|
|
110
110
|
if doc_loaded:
|
|
111
111
|
debug("Config parsed successfully as YAML.")
|
|
@@ -15,7 +15,6 @@ from gitlabform.configuration import Configuration
|
|
|
15
15
|
from gitlabform.gitlab import AccessLevel
|
|
16
16
|
from gitlabform.gitlab import GitLab
|
|
17
17
|
|
|
18
|
-
|
|
19
18
|
# Configuration transformers are classes which take the input configuration as YAML and change it
|
|
20
19
|
# to from the more user-friendly input to an output that is more applicable to passing to GitLab
|
|
21
20
|
# over its API.
|
|
@@ -26,7 +25,6 @@ from gitlabform.gitlab import GitLab
|
|
|
26
25
|
|
|
27
26
|
class ConfigurationTransformers:
|
|
28
27
|
def __init__(self, gitlab: GitLab):
|
|
29
|
-
self.merge_request_approvals_transformer = MergeRequestApprovalsTransformer(gitlab)
|
|
30
28
|
self.user_transformer = UserTransformer(gitlab)
|
|
31
29
|
self.group_transformer = GroupTransformer(gitlab)
|
|
32
30
|
self.implicit_name_transformer = ImplicitNameTransformer(gitlab)
|
|
@@ -36,10 +34,6 @@ class ConfigurationTransformers:
|
|
|
36
34
|
config_before = ez_yaml.to_string(obj=configuration.config, options={})
|
|
37
35
|
debug(f"Config BEFORE transformations:\n{config_before}")
|
|
38
36
|
|
|
39
|
-
# this needs to run before user and group transformer as it may contain users and group
|
|
40
|
-
# names to convert to ids
|
|
41
|
-
self.merge_request_approvals_transformer.transform(configuration)
|
|
42
|
-
|
|
43
37
|
self.user_transformer.transform(configuration)
|
|
44
38
|
self.group_transformer.transform(configuration)
|
|
45
39
|
self.implicit_name_transformer.transform(configuration)
|
|
@@ -263,91 +257,3 @@ class AccessLevelsTransformer(ConfigurationTransformer):
|
|
|
263
257
|
# this just means that we haven't found any keys in YAML
|
|
264
258
|
# under the given path
|
|
265
259
|
pass
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
#
|
|
269
|
-
# TODO: remove below code in v4.x
|
|
270
|
-
#
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
class MergeRequestApprovalsTransformer(ConfigurationTransformer):
|
|
274
|
-
def __init__(self, gitlab: GitLab):
|
|
275
|
-
# this transformer doesn't need to call gitlab
|
|
276
|
-
pass
|
|
277
|
-
|
|
278
|
-
def _do_transform(self, configuration: Configuration) -> None:
|
|
279
|
-
logging_args = SimpleNamespace(quiet=False, verbose=False, debug=False)
|
|
280
|
-
processor = Processor(ConsolePrinter(logging_args), configuration.config)
|
|
281
|
-
|
|
282
|
-
try:
|
|
283
|
-
for node_coordinate in processor.get_nodes(
|
|
284
|
-
"projects_and_groups.*.merge_requests",
|
|
285
|
-
mustexist=True,
|
|
286
|
-
):
|
|
287
|
-
old_syntax_found = False
|
|
288
|
-
|
|
289
|
-
where_to_add_new_syntax = node_coordinate.parent
|
|
290
|
-
|
|
291
|
-
old_syntax = node_coordinate.node
|
|
292
|
-
|
|
293
|
-
approvals_required_guessed = True
|
|
294
|
-
approvals_required = 2
|
|
295
|
-
|
|
296
|
-
# approvals configurations
|
|
297
|
-
if "approvals" in old_syntax:
|
|
298
|
-
old_syntax_found = True
|
|
299
|
-
|
|
300
|
-
if "approvals_before_merge" in old_syntax["approvals"]:
|
|
301
|
-
# this setting is now moved inside the approval rules, so remove it from here
|
|
302
|
-
# but store it for adding there
|
|
303
|
-
approvals_required = old_syntax["approvals"]["approvals_before_merge"]
|
|
304
|
-
approvals_required_guessed = False
|
|
305
|
-
old_syntax["approvals"].pop("approvals_before_merge")
|
|
306
|
-
|
|
307
|
-
if old_syntax["approvals"]:
|
|
308
|
-
# add the settings, if there are left any after removing 'approvals_before_merge'
|
|
309
|
-
where_to_add_new_syntax["merge_requests_approvals"] = old_syntax["approvals"]
|
|
310
|
-
|
|
311
|
-
# approval rules
|
|
312
|
-
if "approvers" in old_syntax or "approver_groups" in old_syntax or not approvals_required_guessed:
|
|
313
|
-
old_syntax_found = True
|
|
314
|
-
|
|
315
|
-
where_to_add_new_syntax["merge_requests_approval_rules"] = {
|
|
316
|
-
"legacy": {
|
|
317
|
-
"approvals_required": approvals_required,
|
|
318
|
-
"name": APPROVAL_RULE_NAME,
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
if "approvers" in old_syntax:
|
|
323
|
-
where_to_add_new_syntax["merge_requests_approval_rules"]["legacy"]["users"] = old_syntax[
|
|
324
|
-
"approvers"
|
|
325
|
-
]
|
|
326
|
-
if "approver_groups" in old_syntax:
|
|
327
|
-
where_to_add_new_syntax["merge_requests_approval_rules"]["legacy"]["groups"] = old_syntax[
|
|
328
|
-
"approver_groups"
|
|
329
|
-
]
|
|
330
|
-
|
|
331
|
-
if "remove_other_approval_rules" in old_syntax and old_syntax["remove_other_approval_rules"]:
|
|
332
|
-
old_syntax_found = True
|
|
333
|
-
where_to_add_new_syntax["merge_requests_approval_rules"]["enforce"] = True
|
|
334
|
-
|
|
335
|
-
if old_syntax_found:
|
|
336
|
-
where_to_add_new_syntax.pop("merge_requests")
|
|
337
|
-
|
|
338
|
-
warning(
|
|
339
|
-
"The 'merge_requests' configuration section syntax works but is deprecated and will be removed "
|
|
340
|
-
"in the next major version of GitLabForm. "
|
|
341
|
-
"Please migrate to the new syntax using the 'merge_requests_approvals' "
|
|
342
|
-
"and the 'merge_requests_approval_rules' sections."
|
|
343
|
-
)
|
|
344
|
-
if approvals_required_guessed:
|
|
345
|
-
warning(
|
|
346
|
-
"'approvals_before_merge' not found in the old 'merge_requests' configuration section",
|
|
347
|
-
"- assuming that it is set to 2.",
|
|
348
|
-
)
|
|
349
|
-
|
|
350
|
-
except YAMLPathException:
|
|
351
|
-
# this just means that we haven't found any keys in YAML
|
|
352
|
-
# under the given path
|
|
353
|
-
pass
|
|
@@ -8,7 +8,6 @@ from gitlab import Gitlab as GitlabClient, GraphQL
|
|
|
8
8
|
from gitlabform.gitlab.commits import GitLabCommits
|
|
9
9
|
from gitlabform.gitlab.group_badges import GitLabGroupBadges
|
|
10
10
|
from gitlabform.gitlab.group_ldap_links import GitLabGroupLDAPLinks
|
|
11
|
-
from gitlabform.gitlab.group_variables import GitLabGroupVariables
|
|
12
11
|
from gitlabform.gitlab.merge_requests import GitLabMergeRequests
|
|
13
12
|
from gitlabform.gitlab.pipelines import GitLabPipelines
|
|
14
13
|
from gitlabform.gitlab.project_badges import GitLabProjectBadges
|
|
@@ -20,8 +19,6 @@ from gitlabform.gitlab.project_merge_requests_approvals import (
|
|
|
20
19
|
GitLabProjectMergeRequestsApprovals,
|
|
21
20
|
)
|
|
22
21
|
from gitlabform.gitlab.python_gitlab import PythonGitlab
|
|
23
|
-
from gitlabform.gitlab.variables import GitLabVariables
|
|
24
|
-
from gitlabform.gitlab.project_security_settings import GitlabProjectSecuritySettings
|
|
25
22
|
|
|
26
23
|
|
|
27
24
|
@enum.unique
|
|
@@ -55,14 +52,11 @@ class GitLab(
|
|
|
55
52
|
GitLabMergeRequests,
|
|
56
53
|
GitLabGroupLDAPLinks,
|
|
57
54
|
GitLabGroupBadges,
|
|
58
|
-
GitLabGroupVariables,
|
|
59
55
|
GitLabPipelines,
|
|
60
56
|
GitLabProjectBadges,
|
|
61
57
|
GitLabProjectDeployKeys,
|
|
62
58
|
GitLabProjectProtectedEnvironments,
|
|
63
59
|
GitLabProjectMergeRequestsApprovals,
|
|
64
|
-
GitLabVariables,
|
|
65
|
-
GitlabProjectSecuritySettings,
|
|
66
60
|
):
|
|
67
61
|
pass
|
|
68
62
|
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
import os
|
|
3
|
+
import re
|
|
3
4
|
from logging import debug
|
|
5
|
+
from typing import Union
|
|
4
6
|
from urllib import parse
|
|
5
7
|
|
|
8
|
+
from packaging import version
|
|
9
|
+
|
|
6
10
|
from importlib.metadata import version as package_version
|
|
7
11
|
import requests
|
|
8
12
|
|
|
@@ -90,6 +94,42 @@ class GitLabCore:
|
|
|
90
94
|
def get_project(self, project_and_group_or_id):
|
|
91
95
|
return self._make_requests_to_api("projects/%s", project_and_group_or_id)
|
|
92
96
|
|
|
97
|
+
def is_version_at_least(self, min_version: Union[str, version.Version]) -> bool:
|
|
98
|
+
"""
|
|
99
|
+
Check if GitLab server version is at least the specified version
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
min_version: Version string like "15.4.0" or "16.0", or a Version object
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
bool: True if server version is >= min_version, False otherwise
|
|
106
|
+
"""
|
|
107
|
+
current_version = "0.0.0"
|
|
108
|
+
|
|
109
|
+
if self.version != "unknown":
|
|
110
|
+
sem_ver_regex = "^\d*\.\d*\.\d*"
|
|
111
|
+
# Get the pure semantic version from self.version, for example Gitlab will return 18.2.1-ee
|
|
112
|
+
match = re.search(sem_ver_regex, self.version)
|
|
113
|
+
if match:
|
|
114
|
+
current_version = match.group()
|
|
115
|
+
|
|
116
|
+
if isinstance(min_version, str):
|
|
117
|
+
min_version = version.parse(min_version)
|
|
118
|
+
|
|
119
|
+
return version.parse(current_version) >= min_version
|
|
120
|
+
|
|
121
|
+
def is_version_less_than(self, max_version: Union[str, version.Version]) -> bool:
|
|
122
|
+
"""
|
|
123
|
+
Check if GitLab server version is less than the specified version
|
|
124
|
+
Args:
|
|
125
|
+
max_version: Version string like "15.4.0" or "16.0", or a Version object
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
bool: True if server version is < max_version, False otherwise
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
return not self.is_version_at_least(max_version)
|
|
132
|
+
|
|
93
133
|
@functools.lru_cache()
|
|
94
134
|
def _get_user_id(self, username: str) -> int:
|
|
95
135
|
users = self._make_requests_to_api("users?username=%s", username, "GET")
|
|
@@ -116,12 +116,6 @@ class GitLabProjects(GitLabCore):
|
|
|
116
116
|
except NotFoundException:
|
|
117
117
|
return []
|
|
118
118
|
|
|
119
|
-
def get_project_settings(self, project_and_group_name):
|
|
120
|
-
try:
|
|
121
|
-
return self._make_requests_to_api("projects/%s", project_and_group_name)
|
|
122
|
-
except NotFoundException:
|
|
123
|
-
return dict()
|
|
124
|
-
|
|
125
119
|
def get_groups_from_project(self, project_and_group_name):
|
|
126
120
|
# couldn't find an API call that was giving me directly
|
|
127
121
|
# the shared groups, so I'm using directly the GET /projects/:id call
|
|
@@ -5,7 +5,6 @@ from cli_ui import fatal
|
|
|
5
5
|
from gitlabform.constants import EXIT_INVALID_INPUT
|
|
6
6
|
from gitlabform.lists import OmissionReason, Groups, Projects
|
|
7
7
|
|
|
8
|
-
|
|
9
8
|
# Groups and projects filters jobs is to omit some groups and projects that GitLabForm is requested
|
|
10
9
|
# to process for a speed-up.
|
|
11
10
|
#
|
|
@@ -43,10 +43,8 @@ class AbstractProcessor(ABC):
|
|
|
43
43
|
project_transfer_source = ""
|
|
44
44
|
try:
|
|
45
45
|
project_transfer_source = configuration["project"]["transfer_from"]
|
|
46
|
-
verbose(
|
|
47
|
-
|
|
48
|
-
diffing config from transfer source project {project_transfer_source}."""
|
|
49
|
-
)
|
|
46
|
+
verbose(f"""Project {project_or_project_and_group} is configured to be transferred,
|
|
47
|
+
diffing config from transfer source project {project_transfer_source}.""")
|
|
50
48
|
except KeyError:
|
|
51
49
|
pass
|
|
52
50
|
|
{gitlabform-4.7.0 → gitlabform-5.0.0}/gitlabform/processors/group/group_saml_links_processor.py
RENAMED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
from logging import debug
|
|
1
|
+
from logging import debug, warning
|
|
2
2
|
from typing import List
|
|
3
|
+
from cli_ui import info
|
|
3
4
|
|
|
4
5
|
from gitlabform.gitlab import GitLab
|
|
5
6
|
from gitlab.v4.objects import Group, GroupSAMLGroupLink
|
|
@@ -9,13 +10,13 @@ from gitlabform.processors.abstract_processor import AbstractProcessor
|
|
|
9
10
|
class GroupSAMLLinksProcessor(AbstractProcessor):
|
|
10
11
|
|
|
11
12
|
def __init__(self, gitlab: GitLab):
|
|
12
|
-
super().__init__("
|
|
13
|
+
super().__init__("group_saml_links", gitlab)
|
|
13
14
|
|
|
14
15
|
def _process_configuration(self, group_path: str, configuration: dict) -> None:
|
|
15
16
|
"""Process the SAML links configuration for a group."""
|
|
16
17
|
|
|
17
|
-
configured_links = configuration.get("
|
|
18
|
-
enforce_links = configuration.get("
|
|
18
|
+
configured_links = configuration.get("group_saml_links", {})
|
|
19
|
+
enforce_links = configuration.get("group_saml_links|enforce", False)
|
|
19
20
|
|
|
20
21
|
group: Group = self.gl.get_group_by_path_cached(group_path)
|
|
21
22
|
existing_links: List[GroupSAMLGroupLink] = group.saml_group_links.list(get_all=True)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from typing import Any, Dict
|
|
2
|
+
from cli_ui import debug as verbose
|
|
3
|
+
from gitlabform.gitlab import GitLab
|
|
4
|
+
from gitlab.v4.objects import Group
|
|
5
|
+
|
|
6
|
+
from gitlabform.processors.abstract_processor import AbstractProcessor
|
|
7
|
+
from gitlabform.processors.util.variables_processor import VariablesProcessor
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class GroupVariablesProcessor(AbstractProcessor):
|
|
11
|
+
def __init__(self, gitlab: GitLab):
|
|
12
|
+
super().__init__("group_variables", gitlab)
|
|
13
|
+
self._variables_processor = VariablesProcessor(self._needs_update)
|
|
14
|
+
|
|
15
|
+
def _process_configuration(self, project_and_group: str, configuration: Dict[str, Any]) -> None:
|
|
16
|
+
group: Group = self.gl.get_group_by_path_cached(project_and_group)
|
|
17
|
+
|
|
18
|
+
configured_variables = configuration.get("group_variables", {})
|
|
19
|
+
enforce_mode: bool = configured_variables.get("enforce", False)
|
|
20
|
+
|
|
21
|
+
if enforce_mode:
|
|
22
|
+
verbose(f"Enforce mode enabled for variables in {project_and_group}")
|
|
23
|
+
# Remove 'enforce' key from the config so that it's not treated as a variable
|
|
24
|
+
configured_variables.pop("enforce")
|
|
25
|
+
|
|
26
|
+
self._variables_processor.process_variables(group, configured_variables, enforce_mode)
|
|
@@ -35,7 +35,7 @@ from gitlabform.processors.project.resource_groups_processor import (
|
|
|
35
35
|
)
|
|
36
36
|
from gitlabform.processors.project.schedules_processor import SchedulesProcessor
|
|
37
37
|
from gitlabform.processors.project.tags_processor import TagsProcessor
|
|
38
|
-
from gitlabform.processors.project.
|
|
38
|
+
from gitlabform.processors.project.project_variables_processor import ProjectVariablesProcessor
|
|
39
39
|
from gitlabform.processors.shared.protected_environments_processor import (
|
|
40
40
|
ProtectedEnvironmentsProcessor,
|
|
41
41
|
)
|
|
@@ -64,7 +64,7 @@ class ProjectProcessors(AbstractProcessors):
|
|
|
64
64
|
ProjectLabelsProcessor(gitlab),
|
|
65
65
|
JobTokenScopeProcessor(gitlab),
|
|
66
66
|
DeployKeysProcessor(gitlab),
|
|
67
|
-
|
|
67
|
+
ProjectVariablesProcessor(gitlab),
|
|
68
68
|
BranchesProcessor(gitlab, strict),
|
|
69
69
|
TagsProcessor(gitlab, strict),
|
|
70
70
|
IntegrationsProcessor(gitlab),
|