gitlabform 4.0.0__tar.gz → 4.0.2__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.0 → gitlabform-4.0.2}/PKG-INFO +2 -2
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/gitlab/__init__.py +0 -4
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/multiple_entities_processor.py +16 -1
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/project/__init__.py +7 -1
- gitlabform-4.0.2/gitlabform/processors/project/branches_processor.py +151 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/project/files_processor.py +118 -81
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform.egg-info/PKG-INFO +2 -2
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform.egg-info/SOURCES.txt +0 -4
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform.egg-info/requires.txt +1 -1
- {gitlabform-4.0.0 → gitlabform-4.0.2}/setup.py +1 -1
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/__init__.py +66 -5
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_branches.py +10 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_files.py +23 -1
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_transfer_project.py +8 -3
- gitlabform-4.0.0/gitlabform/gitlab/branches.py +0 -110
- gitlabform-4.0.0/gitlabform/gitlab/repositories.py +0 -64
- gitlabform-4.0.0/gitlabform/processors/project/branches_processor.py +0 -15
- gitlabform-4.0.0/gitlabform/processors/util/branch_protector.py +0 -358
- gitlabform-4.0.0/tests/unit/processors/test_branch_protector.py +0 -27
- {gitlabform-4.0.0 → gitlabform-4.0.2}/LICENSE +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/README.md +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/__init__.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/configuration/__init__.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/configuration/common.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/configuration/core.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/configuration/groups.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/configuration/projects.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/configuration/transform.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/constants.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/gitlab/commits.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/gitlab/core.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/gitlab/group_badges.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/gitlab/group_ldap_links.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/gitlab/group_variables.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/gitlab/groups.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/gitlab/merge_requests.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/gitlab/pipelines.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/gitlab/project_badges.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/gitlab/project_deploy_keys.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/gitlab/project_merge_requests_approvals.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/gitlab/project_protected_environments.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/gitlab/projects.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/gitlab/python_gitlab.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/gitlab/users.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/gitlab/variables.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/lists/__init__.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/lists/filter.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/lists/groups.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/lists/projects.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/output.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/__init__.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/abstract_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/application/__init__.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/application/application_settings_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/defining_keys.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/group/__init__.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/group/group_badges_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/group/group_labels_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/group/group_ldap_links_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/group/group_members_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/group/group_saml_links_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/group/group_settings_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/group/group_variables_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/project/badges_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/project/deploy_keys_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/project/hooks_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/project/integrations_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/project/job_token_scope_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/project/members_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/project/merge_requests_approval_rules.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/project/merge_requests_approvals.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/project/project_labels_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/project/project_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/project/project_push_rules_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/project/project_settings_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/project/resource_groups_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/project/schedules_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/project/tags_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/project/variables_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/shared/__init__.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/shared/protected_environments_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/single_entity_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/util/__init__.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/util/decorators.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/util/difference_logger.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/processors/util/labels_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/run.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform/util.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform.egg-info/dependency_links.txt +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform.egg-info/entry_points.txt +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/gitlabform.egg-info/top_level.txt +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/setup.cfg +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/__init__.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/conftest.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/__init__.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_application_settings.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_archive_project.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_badges.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_deploy_keys.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_deploy_keys_all_projects.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_files_templates.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_group_badges.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_group_labels.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_group_members_case_insensitive.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_group_members_groups.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_group_members_users.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_group_settings.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_group_variables.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_hooks.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_integrations.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_job_token_scope.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_members.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_members_add_group.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_members_enforce.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_project_group_members_case_insensitive.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_project_labels.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_project_members_case_insensitve.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_project_settings.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_resource_groups.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_running.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_schedules.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_tags.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_token_from_config.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/acceptance/standard/test_variables.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/unit/__init__.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/unit/configuration/__init__.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/unit/configuration/test_case_sensitivity.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/unit/configuration/test_inheritance_break_projects_and_groups.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/unit/configuration/test_inheritance_break_subgroups.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/unit/configuration/test_inheritance_break_validation.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/unit/configuration/test_projects_and_groups.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/unit/configuration/test_skip_groups_skip_projects.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/unit/configuration/test_subgroups.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/unit/configuration/test_yaml_version.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/unit/processors/__init__.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/unit/processors/test_abstract_processor.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/unit/processors/test_difference_logger.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/unit/processors/test_schedules_processor_extended_cron_pattern.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/unit/test_access_levels.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/unit/test_non_empty_configs_provider.py +0 -0
- {gitlabform-4.0.0 → gitlabform-4.0.2}/tests/unit/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: gitlabform
|
|
3
|
-
Version: 4.0.
|
|
3
|
+
Version: 4.0.2
|
|
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
|
|
@@ -24,7 +24,7 @@ Requires-Dist: Jinja2==3.1.4
|
|
|
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
|
-
Requires-Dist: packaging==24.
|
|
27
|
+
Requires-Dist: packaging==24.2
|
|
28
28
|
Requires-Dist: python-gitlab==5.0.0
|
|
29
29
|
Requires-Dist: requests==2.32.3
|
|
30
30
|
Requires-Dist: ruamel.yaml==0.17.21
|
|
@@ -2,7 +2,6 @@ import enum
|
|
|
2
2
|
|
|
3
3
|
from typing import List
|
|
4
4
|
|
|
5
|
-
from gitlabform.gitlab.branches import GitLabBranches
|
|
6
5
|
from gitlabform.gitlab.commits import GitLabCommits
|
|
7
6
|
from gitlabform.gitlab.group_badges import GitLabGroupBadges
|
|
8
7
|
from gitlabform.gitlab.group_ldap_links import GitLabGroupLDAPLinks
|
|
@@ -19,7 +18,6 @@ from gitlabform.gitlab.project_merge_requests_approvals import (
|
|
|
19
18
|
)
|
|
20
19
|
from gitlabform.gitlab.python_gitlab import PythonGitlab
|
|
21
20
|
from gitlabform.gitlab.variables import GitLabVariables
|
|
22
|
-
from gitlabform.gitlab.repositories import GitLabRepositories
|
|
23
21
|
from gitlabform.gitlab.users import GitLabUsers
|
|
24
22
|
|
|
25
23
|
|
|
@@ -49,10 +47,8 @@ class AccessLevel(enum.IntEnum):
|
|
|
49
47
|
|
|
50
48
|
|
|
51
49
|
class GitLab(
|
|
52
|
-
GitLabBranches,
|
|
53
50
|
GitLabCommits,
|
|
54
51
|
GitLabMergeRequests,
|
|
55
|
-
GitLabRepositories,
|
|
56
52
|
GitLabGroupLDAPLinks,
|
|
57
53
|
GitLabGroupBadges,
|
|
58
54
|
GitLabGroupVariables,
|
|
@@ -4,7 +4,7 @@ from cli_ui import fatal
|
|
|
4
4
|
|
|
5
5
|
import abc
|
|
6
6
|
from typing import Callable, Union, Any
|
|
7
|
-
|
|
7
|
+
import time
|
|
8
8
|
from gitlabform.constants import EXIT_INVALID_INPUT
|
|
9
9
|
from gitlabform.gitlab import GitLab
|
|
10
10
|
from gitlabform.processors.abstract_processor import AbstractProcessor
|
|
@@ -70,6 +70,21 @@ class MultipleEntitiesProcessor(AbstractProcessor, metaclass=abc.ABCMeta):
|
|
|
70
70
|
else:
|
|
71
71
|
enforce = False
|
|
72
72
|
|
|
73
|
+
if (
|
|
74
|
+
"members" in configuration
|
|
75
|
+
and ("protected_environments" or "merge_requests_approval_rules")
|
|
76
|
+
in configuration
|
|
77
|
+
):
|
|
78
|
+
# When gitlabform needs to update project membership and also configure
|
|
79
|
+
# settings that are dependent on the members (i.e. environment protection
|
|
80
|
+
# or MR approval rule), there seems to be an issue in GitLab. Automated
|
|
81
|
+
# acceptance tests in gitlabform creates new user and adds to the project
|
|
82
|
+
# followed by configuring other setting. In that scenario need to wait a little
|
|
83
|
+
# before calling GitLab's REST API for processing other settings. Otherwise
|
|
84
|
+
# the users are not available to be configured in other settings and it
|
|
85
|
+
# does not return any error either"
|
|
86
|
+
time.sleep(2)
|
|
87
|
+
|
|
73
88
|
# TODO: move/convert this to a configuration validation phase
|
|
74
89
|
self._find_duplicates(project_or_group, entities_in_configuration)
|
|
75
90
|
|
|
@@ -55,8 +55,15 @@ class ProjectProcessors(AbstractProcessors):
|
|
|
55
55
|
def __init__(self, gitlab: GitLab, config: Configuration, strict: bool):
|
|
56
56
|
super().__init__(gitlab, config, strict)
|
|
57
57
|
self.processors: List[AbstractProcessor] = [
|
|
58
|
+
# Order of processors matter. GitLabForm will process config sections
|
|
59
|
+
# in the order listed below. Settings that are related to each other,
|
|
60
|
+
# should be ordered accordingly. For example, branch protection or MR
|
|
61
|
+
# approvals can configure specific users, but the user must be a
|
|
62
|
+
# member of the project. So, project membership must be processed
|
|
63
|
+
# before those processors.
|
|
58
64
|
ProjectProcessor(gitlab),
|
|
59
65
|
ProjectSettingsProcessor(gitlab),
|
|
66
|
+
MembersProcessor(gitlab),
|
|
60
67
|
ProjectPushRulesProcessor(gitlab),
|
|
61
68
|
ProjectLabelsProcessor(gitlab),
|
|
62
69
|
JobTokenScopeProcessor(gitlab),
|
|
@@ -67,7 +74,6 @@ class ProjectProcessors(AbstractProcessors):
|
|
|
67
74
|
IntegrationsProcessor(gitlab),
|
|
68
75
|
FilesProcessor(gitlab, config, strict),
|
|
69
76
|
HooksProcessor(gitlab),
|
|
70
|
-
MembersProcessor(gitlab),
|
|
71
77
|
SchedulesProcessor(gitlab),
|
|
72
78
|
BadgesProcessor(gitlab),
|
|
73
79
|
ResourceGroupsProcessor(gitlab),
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from logging import debug, info
|
|
3
|
+
from cli_ui import warning, fatal
|
|
4
|
+
from gitlab.v4.objects import Project, ProjectBranch, ProjectProtectedBranch
|
|
5
|
+
from gitlab import (
|
|
6
|
+
GitlabGetError,
|
|
7
|
+
GitlabDeleteError,
|
|
8
|
+
GitlabCreateError,
|
|
9
|
+
)
|
|
10
|
+
from gitlabform.constants import EXIT_INVALID_INPUT, EXIT_PROCESSING_ERROR
|
|
11
|
+
from gitlabform.gitlab import GitLab
|
|
12
|
+
from gitlabform.processors.abstract_processor import AbstractProcessor
|
|
13
|
+
import time
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BranchesProcessor(AbstractProcessor):
|
|
17
|
+
def __init__(self, gitlab: GitLab, strict: bool):
|
|
18
|
+
super().__init__("branches", gitlab)
|
|
19
|
+
self.strict = strict
|
|
20
|
+
|
|
21
|
+
def _process_configuration(self, project_and_group: str, configuration: dict):
|
|
22
|
+
if "members" in configuration:
|
|
23
|
+
# When gitlabform needs to update project membership and also
|
|
24
|
+
# configure branch protection, there seems to be a race condition
|
|
25
|
+
# or delay in GitLab. Automated acceptance tests in gitlabform
|
|
26
|
+
# creates new user and adds to the project followed by configuring
|
|
27
|
+
# branch protection setting. In that scenario need to wait a little
|
|
28
|
+
# before calling GitLab's REST API for branch protection. Otherwise
|
|
29
|
+
# the API returns error code 422 with an message like "Push access
|
|
30
|
+
# levels user is not a member of the project"
|
|
31
|
+
|
|
32
|
+
time.sleep(2)
|
|
33
|
+
|
|
34
|
+
project: Project = self.gl.get_project_by_path_cached(project_and_group)
|
|
35
|
+
|
|
36
|
+
for branch in sorted(configuration["branches"]):
|
|
37
|
+
branch_configuration: dict = self.transform_branch_config(
|
|
38
|
+
configuration["branches"][branch]
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
self.process_branch_protection(project, branch, branch_configuration)
|
|
42
|
+
|
|
43
|
+
def process_branch_protection(
|
|
44
|
+
self, project: Project, branch_name: str, branch_config: dict
|
|
45
|
+
):
|
|
46
|
+
"""
|
|
47
|
+
Process branch protection according to gitlabform config.
|
|
48
|
+
"""
|
|
49
|
+
branch: Optional[ProjectBranch] = None
|
|
50
|
+
protected_branch: Optional[ProjectProtectedBranch] = None
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
branch = project.branches.get(branch_name)
|
|
54
|
+
except GitlabGetError:
|
|
55
|
+
message = f"Branch '{branch_name}' not found when trying to processing it to be protected/unprotected!"
|
|
56
|
+
if self.strict:
|
|
57
|
+
fatal(
|
|
58
|
+
message,
|
|
59
|
+
exit_code=EXIT_INVALID_INPUT,
|
|
60
|
+
)
|
|
61
|
+
else:
|
|
62
|
+
warning(message)
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
protected_branch = project.protectedbranches.get(branch_name)
|
|
66
|
+
except GitlabGetError:
|
|
67
|
+
message = f"The branch '{branch_name}' is not protected!"
|
|
68
|
+
debug(message)
|
|
69
|
+
|
|
70
|
+
if branch and branch_config.get("protected"):
|
|
71
|
+
if protected_branch and self._needs_update(
|
|
72
|
+
protected_branch.attributes, branch_config
|
|
73
|
+
):
|
|
74
|
+
# Need to unprotect the branch and then re-protect again using current config
|
|
75
|
+
# Another option would be to "update" protected branch. But, GitLab's API for
|
|
76
|
+
# updating protected branch requires retrieving id of the existing rule/config
|
|
77
|
+
# such as 'allowed_to_push'. See: https://docs.gitlab.com/ee/api/protected_branches.html#example-update-a-push_access_level-record
|
|
78
|
+
# This could involve more data processing. The data for updating vs creating a
|
|
79
|
+
# protected branch is not the same. So, removing existing branch protection and
|
|
80
|
+
# reconfiguring branch protection seems simpler.
|
|
81
|
+
self.unprotect_branch(protected_branch)
|
|
82
|
+
self.protect_branch(project, branch, branch_config)
|
|
83
|
+
elif not protected_branch:
|
|
84
|
+
self.protect_branch(project, branch, branch_config)
|
|
85
|
+
elif protected_branch and not branch_config.get("protected"):
|
|
86
|
+
self.unprotect_branch(protected_branch)
|
|
87
|
+
|
|
88
|
+
def protect_branch(
|
|
89
|
+
self, project: Project, branch: ProjectBranch, branch_config: dict
|
|
90
|
+
):
|
|
91
|
+
"""
|
|
92
|
+
Protect a branch using given config.
|
|
93
|
+
Raise exception if running in strict mode.
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
debug("Setting branch '%s' as protected", branch.name)
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
project.protectedbranches.create({"name": branch.name, **branch_config})
|
|
100
|
+
except GitlabCreateError as e:
|
|
101
|
+
message = (
|
|
102
|
+
f"Protecting branch '{branch.name}' failed! Error '{e.error_message}"
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
if self.strict:
|
|
106
|
+
fatal(
|
|
107
|
+
message,
|
|
108
|
+
exit_code=EXIT_PROCESSING_ERROR,
|
|
109
|
+
)
|
|
110
|
+
else:
|
|
111
|
+
warning(message)
|
|
112
|
+
|
|
113
|
+
def unprotect_branch(self, protected_branch: ProjectProtectedBranch):
|
|
114
|
+
"""
|
|
115
|
+
Unprotect a branch.
|
|
116
|
+
Raise exception if running in strict mode.
|
|
117
|
+
"""
|
|
118
|
+
|
|
119
|
+
debug("Setting branch '%s' as unprotected", protected_branch.name)
|
|
120
|
+
|
|
121
|
+
try:
|
|
122
|
+
# The delete method doesn't delete the actual branch.
|
|
123
|
+
# It only unprotects the branch.
|
|
124
|
+
protected_branch.delete()
|
|
125
|
+
except GitlabDeleteError as e:
|
|
126
|
+
message = f"Branch '{protected_branch.name}' could not be unprotected! Error '{e.error_message}"
|
|
127
|
+
if self.strict:
|
|
128
|
+
fatal(
|
|
129
|
+
message,
|
|
130
|
+
exit_code=EXIT_PROCESSING_ERROR,
|
|
131
|
+
)
|
|
132
|
+
else:
|
|
133
|
+
warning(message)
|
|
134
|
+
|
|
135
|
+
def transform_branch_config(self, branch_config: dict):
|
|
136
|
+
"""
|
|
137
|
+
The branch configuration in gitlabform supports passing users or group using username
|
|
138
|
+
or group name but GitLab only supports their id. This method will transform the
|
|
139
|
+
config by replacing them with ids.
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
for key in branch_config:
|
|
143
|
+
if isinstance(branch_config[key], list):
|
|
144
|
+
for item in branch_config[key]:
|
|
145
|
+
if isinstance(item, dict):
|
|
146
|
+
if "user" in item:
|
|
147
|
+
item["user_id"] = self.gl.get_user_id(item.pop("user"))
|
|
148
|
+
elif "group" in item:
|
|
149
|
+
item["group_id"] = self.gl.get_group_id(item.pop("group"))
|
|
150
|
+
|
|
151
|
+
return branch_config
|
|
@@ -5,15 +5,18 @@ from pathlib import Path
|
|
|
5
5
|
from logging import debug
|
|
6
6
|
from cli_ui import debug as verbose
|
|
7
7
|
from cli_ui import warning, fatal
|
|
8
|
+
from typing import List
|
|
8
9
|
|
|
9
10
|
from jinja2 import Environment, FileSystemLoader
|
|
11
|
+
from gitlab import GitlabGetError, GitlabUpdateError
|
|
12
|
+
from gitlab.v4.objects import Project, ProjectFile, ProjectBranch
|
|
13
|
+
from gitlab.base import RESTObject
|
|
10
14
|
|
|
11
15
|
from gitlabform.constants import EXIT_INVALID_INPUT
|
|
12
16
|
from gitlabform.configuration import Configuration
|
|
13
17
|
from gitlabform.gitlab import GitLab
|
|
14
|
-
from gitlabform.gitlab.core import NotFoundException, UnexpectedResponseException
|
|
15
18
|
from gitlabform.processors.abstract_processor import AbstractProcessor
|
|
16
|
-
from gitlabform.processors.
|
|
19
|
+
from gitlabform.processors.project.branches_processor import BranchesProcessor
|
|
17
20
|
|
|
18
21
|
|
|
19
22
|
class FilesProcessor(AbstractProcessor):
|
|
@@ -21,32 +24,38 @@ class FilesProcessor(AbstractProcessor):
|
|
|
21
24
|
super().__init__("files", gitlab)
|
|
22
25
|
self.config = config
|
|
23
26
|
self.strict = strict
|
|
24
|
-
self.
|
|
27
|
+
self.branch_processor = BranchesProcessor(gitlab, strict)
|
|
25
28
|
|
|
26
29
|
def _process_configuration(self, project_and_group: str, configuration: dict):
|
|
27
30
|
for file in sorted(configuration["files"]):
|
|
31
|
+
project: Project = self.gl.get_project_by_path_cached(project_and_group)
|
|
28
32
|
debug("Processing file '%s'...", file)
|
|
29
33
|
|
|
30
34
|
if configuration.get("files|" + file + "|skip"):
|
|
31
35
|
debug("Skipping file '%s'", file)
|
|
32
36
|
continue
|
|
33
37
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
38
|
+
config_target_ref = configuration["files"][file]["branches"]
|
|
39
|
+
branches_to_update: List[RESTObject] = []
|
|
40
|
+
|
|
41
|
+
if isinstance(config_target_ref, str):
|
|
42
|
+
# Target ref could be either 'all' or 'protected'.
|
|
43
|
+
# Get a list of branches that should be updated.
|
|
44
|
+
if config_target_ref == "all":
|
|
45
|
+
branches_to_update.extend(
|
|
46
|
+
project.branches.list(get_all=True, lazy=True)
|
|
47
|
+
)
|
|
48
|
+
elif config_target_ref == "protected":
|
|
49
|
+
branches_to_update.extend(
|
|
50
|
+
project.protectedbranches.list(get_all=True, lazy=True)
|
|
51
|
+
)
|
|
52
|
+
elif isinstance(config_target_ref, list):
|
|
53
|
+
# Get a list of branches from the config that should be updated.
|
|
54
|
+
for branch_name in config_target_ref:
|
|
55
|
+
try:
|
|
56
|
+
branches_to_update.append(project.branches.get(branch_name))
|
|
57
|
+
except GitlabGetError:
|
|
58
|
+
message = f"! Branch '{branch_name}' not found, not processing file '{file}' in it"
|
|
50
59
|
if self.strict:
|
|
51
60
|
fatal(
|
|
52
61
|
message,
|
|
@@ -55,8 +64,14 @@ class FilesProcessor(AbstractProcessor):
|
|
|
55
64
|
else:
|
|
56
65
|
warning(message)
|
|
57
66
|
|
|
58
|
-
|
|
59
|
-
|
|
67
|
+
debug(
|
|
68
|
+
"File '%s' to be updated in '%s' branche(s)",
|
|
69
|
+
file,
|
|
70
|
+
len(branches_to_update),
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
for branch in branches_to_update:
|
|
74
|
+
verbose(f"Processing file '{file}' in branch '{branch.name}'")
|
|
60
75
|
|
|
61
76
|
if configuration.get(
|
|
62
77
|
"files|" + file + "|content"
|
|
@@ -69,20 +84,22 @@ class FilesProcessor(AbstractProcessor):
|
|
|
69
84
|
|
|
70
85
|
if configuration.get("files|" + file + "|delete"):
|
|
71
86
|
try:
|
|
72
|
-
|
|
73
|
-
|
|
87
|
+
file_to_delete: ProjectFile = project.files.get(
|
|
88
|
+
file_path=file, ref=branch.name
|
|
89
|
+
)
|
|
90
|
+
debug("Deleting file '%s' in branch '%s'", file, branch.name)
|
|
74
91
|
self.modify_file_dealing_with_branch_protection(
|
|
75
|
-
|
|
92
|
+
project,
|
|
76
93
|
branch,
|
|
77
|
-
|
|
94
|
+
file_to_delete,
|
|
78
95
|
"delete",
|
|
79
96
|
configuration,
|
|
80
97
|
)
|
|
81
|
-
except
|
|
98
|
+
except GitlabGetError:
|
|
82
99
|
debug(
|
|
83
100
|
"Not deleting file '%s' in branch '%s' (already doesn't exist)",
|
|
84
101
|
file,
|
|
85
|
-
branch,
|
|
102
|
+
branch.name,
|
|
86
103
|
)
|
|
87
104
|
else:
|
|
88
105
|
# change or create file
|
|
@@ -118,16 +135,22 @@ class FilesProcessor(AbstractProcessor):
|
|
|
118
135
|
)
|
|
119
136
|
|
|
120
137
|
try:
|
|
121
|
-
|
|
122
|
-
|
|
138
|
+
repo_file: ProjectFile = project.files.get(
|
|
139
|
+
file_path=file, ref=branch.name
|
|
123
140
|
)
|
|
141
|
+
current_content = repo_file.content
|
|
142
|
+
|
|
124
143
|
if current_content != new_content:
|
|
125
144
|
if configuration.get("files|" + file + "|overwrite"):
|
|
126
|
-
debug(
|
|
145
|
+
debug(
|
|
146
|
+
"Changing file '%s' in branch '%s'",
|
|
147
|
+
file,
|
|
148
|
+
branch.name,
|
|
149
|
+
)
|
|
127
150
|
self.modify_file_dealing_with_branch_protection(
|
|
128
|
-
|
|
151
|
+
project,
|
|
129
152
|
branch,
|
|
130
|
-
|
|
153
|
+
repo_file,
|
|
131
154
|
"modify",
|
|
132
155
|
configuration,
|
|
133
156
|
new_content,
|
|
@@ -136,19 +159,19 @@ class FilesProcessor(AbstractProcessor):
|
|
|
136
159
|
debug(
|
|
137
160
|
"Not changing file '%s' in branch '%s' - overwrite flag not set.",
|
|
138
161
|
file,
|
|
139
|
-
branch,
|
|
162
|
+
branch.name,
|
|
140
163
|
)
|
|
141
164
|
else:
|
|
142
165
|
debug(
|
|
143
166
|
"Not changing file '%s' in branch '%s' - it's content is already"
|
|
144
167
|
" as provided)",
|
|
145
168
|
file,
|
|
146
|
-
branch,
|
|
169
|
+
branch.name,
|
|
147
170
|
)
|
|
148
|
-
except
|
|
149
|
-
debug("Creating file '%s' in branch '%s'", file, branch)
|
|
171
|
+
except GitlabGetError:
|
|
172
|
+
debug("Creating file '%s' in branch '%s'", file, branch.name)
|
|
150
173
|
self.modify_file_dealing_with_branch_protection(
|
|
151
|
-
|
|
174
|
+
project,
|
|
152
175
|
branch,
|
|
153
176
|
file,
|
|
154
177
|
"add",
|
|
@@ -162,11 +185,11 @@ class FilesProcessor(AbstractProcessor):
|
|
|
162
185
|
|
|
163
186
|
def modify_file_dealing_with_branch_protection(
|
|
164
187
|
self,
|
|
165
|
-
|
|
166
|
-
branch,
|
|
167
|
-
|
|
168
|
-
operation,
|
|
169
|
-
configuration,
|
|
188
|
+
project: Project,
|
|
189
|
+
branch: RESTObject,
|
|
190
|
+
file_to_operate_on: str | ProjectFile,
|
|
191
|
+
operation: str,
|
|
192
|
+
configuration: dict,
|
|
170
193
|
new_content=None,
|
|
171
194
|
):
|
|
172
195
|
# perhaps your user permissions are ok to just perform this operation regardless
|
|
@@ -174,36 +197,43 @@ class FilesProcessor(AbstractProcessor):
|
|
|
174
197
|
|
|
175
198
|
try:
|
|
176
199
|
self.just_modify_file(
|
|
177
|
-
|
|
200
|
+
project,
|
|
201
|
+
branch,
|
|
202
|
+
file_to_operate_on,
|
|
203
|
+
operation,
|
|
204
|
+
configuration,
|
|
205
|
+
new_content,
|
|
178
206
|
)
|
|
179
207
|
|
|
180
|
-
except
|
|
208
|
+
except GitlabUpdateError as e:
|
|
181
209
|
if (
|
|
182
|
-
e.
|
|
183
|
-
and "You are not allowed to push into this branch" in e.
|
|
210
|
+
e.response_code == 400
|
|
211
|
+
and "You are not allowed to push into this branch" in e.error_message
|
|
184
212
|
):
|
|
185
213
|
# ...but if not, then we can unprotect the branch, but only if we know how to
|
|
186
214
|
# protect it again...
|
|
187
215
|
|
|
188
|
-
if configuration.get("branches|" + branch + "|protected"):
|
|
216
|
+
if configuration.get("branches|" + branch.name + "|protected"):
|
|
189
217
|
debug(
|
|
190
|
-
f"> Temporarily unprotecting the branch to {operation} a file in it..."
|
|
218
|
+
f"> Temporarily unprotecting the branch to '{operation}' a file in it..."
|
|
191
219
|
)
|
|
192
|
-
|
|
220
|
+
# Delete operation on protected branch removes the protection only
|
|
221
|
+
project.protectedbranches.delete(branch.name)
|
|
193
222
|
else:
|
|
194
223
|
fatal(
|
|
195
|
-
f"Operation {operation} on file
|
|
196
|
-
f"
|
|
224
|
+
f"Operation '{operation}' on file in branch {branch.name} not permitted."
|
|
225
|
+
f" We don't have a branch protection configuration provided for this"
|
|
197
226
|
f" branch. Breaking as we cannot unprotect the branch as we would not know"
|
|
198
227
|
f" how to protect it again.",
|
|
199
228
|
EXIT_INVALID_INPUT,
|
|
200
229
|
)
|
|
201
230
|
|
|
202
231
|
try:
|
|
232
|
+
debug("> Attempt updating file again")
|
|
203
233
|
self.just_modify_file(
|
|
204
|
-
|
|
234
|
+
project,
|
|
205
235
|
branch,
|
|
206
|
-
|
|
236
|
+
file_to_operate_on,
|
|
207
237
|
operation,
|
|
208
238
|
configuration,
|
|
209
239
|
new_content,
|
|
@@ -211,10 +241,14 @@ class FilesProcessor(AbstractProcessor):
|
|
|
211
241
|
|
|
212
242
|
finally:
|
|
213
243
|
# ...and protect the branch again after the operation
|
|
214
|
-
if configuration.get("branches|" + branch + "|protected"):
|
|
244
|
+
if configuration.get("branches|" + branch.name + "|protected"):
|
|
215
245
|
debug("> Protecting the branch again.")
|
|
216
|
-
|
|
217
|
-
|
|
246
|
+
project_branch: ProjectBranch = project.branches.get(
|
|
247
|
+
branch.name
|
|
248
|
+
)
|
|
249
|
+
branch_config: dict = configuration["branches"][branch.name]
|
|
250
|
+
self.branch_processor.protect_branch(
|
|
251
|
+
project, project_branch, branch_config
|
|
218
252
|
)
|
|
219
253
|
|
|
220
254
|
else:
|
|
@@ -222,35 +256,38 @@ class FilesProcessor(AbstractProcessor):
|
|
|
222
256
|
|
|
223
257
|
def just_modify_file(
|
|
224
258
|
self,
|
|
225
|
-
|
|
226
|
-
branch,
|
|
227
|
-
|
|
228
|
-
operation,
|
|
229
|
-
configuration,
|
|
259
|
+
project: Project,
|
|
260
|
+
branch: RESTObject,
|
|
261
|
+
file_to_operate_on: str | ProjectFile,
|
|
262
|
+
operation: str,
|
|
263
|
+
configuration: dict,
|
|
230
264
|
new_content=None,
|
|
231
265
|
):
|
|
232
|
-
if operation == "modify":
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
266
|
+
if operation == "modify" and isinstance(file_to_operate_on, ProjectFile):
|
|
267
|
+
file_to_operate_on.content = new_content
|
|
268
|
+
file_to_operate_on.save(
|
|
269
|
+
commit_message=self.get_commit_message_for_file_change(
|
|
270
|
+
"change", file_to_operate_on.file_path, configuration
|
|
271
|
+
),
|
|
272
|
+
branch=branch.name,
|
|
239
273
|
)
|
|
240
|
-
elif operation == "add":
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
274
|
+
elif operation == "add" and isinstance(file_to_operate_on, str):
|
|
275
|
+
project.files.create(
|
|
276
|
+
{
|
|
277
|
+
"file_path": file_to_operate_on,
|
|
278
|
+
"branch": branch.name,
|
|
279
|
+
"content": new_content,
|
|
280
|
+
"commit_message": self.get_commit_message_for_file_change(
|
|
281
|
+
"delete", file_to_operate_on, configuration
|
|
282
|
+
),
|
|
283
|
+
}
|
|
247
284
|
)
|
|
248
|
-
elif operation == "delete":
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
285
|
+
elif operation == "delete" and isinstance(file_to_operate_on, ProjectFile):
|
|
286
|
+
file_to_operate_on.delete(
|
|
287
|
+
commit_message=self.get_commit_message_for_file_change(
|
|
288
|
+
"delete", file_to_operate_on.file_path, configuration
|
|
289
|
+
),
|
|
290
|
+
branch=branch.name,
|
|
254
291
|
)
|
|
255
292
|
|
|
256
293
|
def get_file_content_as_template(self, template, project_and_group, **kwargs):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: gitlabform
|
|
3
|
-
Version: 4.0.
|
|
3
|
+
Version: 4.0.2
|
|
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
|
|
@@ -24,7 +24,7 @@ Requires-Dist: Jinja2==3.1.4
|
|
|
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
|
-
Requires-Dist: packaging==24.
|
|
27
|
+
Requires-Dist: packaging==24.2
|
|
28
28
|
Requires-Dist: python-gitlab==5.0.0
|
|
29
29
|
Requires-Dist: requests==2.32.3
|
|
30
30
|
Requires-Dist: ruamel.yaml==0.17.21
|
|
@@ -20,7 +20,6 @@ gitlabform/configuration/groups.py
|
|
|
20
20
|
gitlabform/configuration/projects.py
|
|
21
21
|
gitlabform/configuration/transform.py
|
|
22
22
|
gitlabform/gitlab/__init__.py
|
|
23
|
-
gitlabform/gitlab/branches.py
|
|
24
23
|
gitlabform/gitlab/commits.py
|
|
25
24
|
gitlabform/gitlab/core.py
|
|
26
25
|
gitlabform/gitlab/group_badges.py
|
|
@@ -35,7 +34,6 @@ gitlabform/gitlab/project_merge_requests_approvals.py
|
|
|
35
34
|
gitlabform/gitlab/project_protected_environments.py
|
|
36
35
|
gitlabform/gitlab/projects.py
|
|
37
36
|
gitlabform/gitlab/python_gitlab.py
|
|
38
|
-
gitlabform/gitlab/repositories.py
|
|
39
37
|
gitlabform/gitlab/users.py
|
|
40
38
|
gitlabform/gitlab/variables.py
|
|
41
39
|
gitlabform/lists/__init__.py
|
|
@@ -79,7 +77,6 @@ gitlabform/processors/project/variables_processor.py
|
|
|
79
77
|
gitlabform/processors/shared/__init__.py
|
|
80
78
|
gitlabform/processors/shared/protected_environments_processor.py
|
|
81
79
|
gitlabform/processors/util/__init__.py
|
|
82
|
-
gitlabform/processors/util/branch_protector.py
|
|
83
80
|
gitlabform/processors/util/decorators.py
|
|
84
81
|
gitlabform/processors/util/difference_logger.py
|
|
85
82
|
gitlabform/processors/util/labels_processor.py
|
|
@@ -134,6 +131,5 @@ tests/unit/configuration/test_subgroups.py
|
|
|
134
131
|
tests/unit/configuration/test_yaml_version.py
|
|
135
132
|
tests/unit/processors/__init__.py
|
|
136
133
|
tests/unit/processors/test_abstract_processor.py
|
|
137
|
-
tests/unit/processors/test_branch_protector.py
|
|
138
134
|
tests/unit/processors/test_difference_logger.py
|
|
139
135
|
tests/unit/processors/test_schedules_processor_extended_cron_pattern.py
|