Commit 19791ac6 authored by Adrian DC's avatar Adrian DC
Browse files

feat(entrypoint, gitlab): implement '--{disable,enable}-features'

Signed-off-by: default avatarAdrian DC <radian.dc@gmail.com>
parent 9ba30b62
Loading
Loading
Loading
Loading
+4 −1
Changes for README.md: 4 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -30,7 +30,8 @@ The following step is required before using the tool:
```yaml
usage: gitlab-projects-settings [-h] [--version] [-t TOKEN] [--dry-run] [--exclude-group] [--exclude-subgroups]
                                [--exclude-projects] [--available-features] [--reset-features [KEEP_FEATURES]]
                                [--reset-members] [--set-avatar FILE] [--set-description TEXT] [--update-description]
                                [--disable-features FEATURES] [--enable-features FEATURES] [--reset-members]
                                [--set-avatar FILE] [--set-description TEXT] [--update-description]
                                [--run-housekeeping] [--archive-project | --unarchive-project] [--delete-group]
                                [--delete-project] [--protect-branches] [--protect-tags LEVEL]
                                [gitlab] [path]
@@ -54,6 +55,8 @@ general settings arguments:
  --available-features              # List the available GitLab project features known by the tool
  --reset-features [KEEP_FEATURES]  # Reset features of GitLab projects based on usage
                                    # (Optionally keep features separated by ",")
  --disable-features FEATURES       # List of features to disable separated by ","
  --enable-features FEATURES        # List of features to enable separated by ","
  --reset-members                   # Reset members of GitLab projects and groups
  --set-avatar FILE                 # Set avatar of GitLab projects and groups
  --set-description TEXT            # Set description of GitLab projects and groups
+36 −0
Changes for src/cli/entrypoint.py: 36 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -351,6 +351,42 @@ class Entrypoint:
                      f'{Colors.RESET}')
                Platform.flush()

        # Disable project features
        if options.disable_features:
            features = ', '.join(
                gitlab.project_features_disable(
                    criteria,
                    GitLabFeature.project_features_parse(options.disable_features),
                ))
            if features:
                print(f'{Colors.BOLD}   - Disable features: '
                      f'{Colors.CYAN}{features}'
                      f'{Colors.RESET}')
                Platform.flush()
            else:
                print(f'{Colors.BOLD}   - Disable features: '
                      f'{Colors.GREEN}Already done'
                      f'{Colors.RESET}')
                Platform.flush()

        # Enable project features
        if options.enable_features:
            features = ', '.join(
                gitlab.project_features_enable(
                    criteria,
                    GitLabFeature.project_features_parse(options.enable_features),
                ))
            if features:
                print(f'{Colors.BOLD}   - Enable features: '
                      f'{Colors.CYAN}{features}'
                      f'{Colors.RESET}')
                Platform.flush()
            else:
                print(f'{Colors.BOLD}   - Enable features: '
                      f'{Colors.GREEN}Already done'
                      f'{Colors.RESET}')
                Platform.flush()

        # Reset project members
        if options.reset_members:
            gitlab.project_reset_members(criteria)
+12 −0
Changes for src/cli/main.py: 12 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -107,6 +107,18 @@ def main() -> None:
        help='Reset features of GitLab projects based on usage\n'
        '(Optionally keep features separated by ",")',
    )
    group.add_argument(
        '--disable-features',
        dest='disable_features',
        metavar='FEATURES',
        help='List of features to disable separated by ","',
    )
    group.add_argument(
        '--enable-features',
        dest='enable_features',
        metavar='FEATURES',
        help='List of features to enable separated by ","',
    )
    group.add_argument(
        '--reset-members',
        dest='reset_members',
+375 −1
Changes for src/features/gitlab.py: 375 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@ from gitlab import Gitlab
from gitlab.exceptions import GitlabDeleteError, GitlabGetError, GitlabListError
from gitlab.v4.objects import Group, Namespace, Project, User

# GitLabFeature class
# GitLabFeature class, pylint: disable=too-many-public-methods
class GitLabFeature:

    # Constants
@@ -18,6 +18,14 @@ class GitLabFeature:
    # Enumerations (Access Levels), pylint: disable=too-few-public-methods
    class AccessLevels:
        DISABLED = 'disabled'
        PRIVATE = 'private'
        ENABLED = 'enabled'

    # Enumerations (Visibility), pylint: disable=too-few-public-methods
    class Visibility:
        PRIVATE = 'private'
        INTERNAL = 'internal'
        PUBLIC = 'public'

    # Enumerations (Features), pylint: disable=too-few-public-methods
    class Features:
@@ -241,6 +249,372 @@ class GitLabFeature:
            if feature.lower().startswith(input_feature.strip().lower())
        ]

    # Project disable features, pylint: disable=too-many-branches,too-many-statements
    def project_features_disable(
        self,
        criteria: str,
        features: List[str],
    ) -> List[str]:

        # Variables
        result: List[str] = []
        project = self.__gitlab.projects.get(criteria, statistics=True)

        # Disable feature (Issues)
        if project.issues_enabled \
                and GitLabFeature.Features.ISSUES in features:
            project.issues_access_level = GitLabFeature.AccessLevels.DISABLED
            project.issues_enabled = False
            result += [GitLabFeature.Features.ISSUES]

        # Disable feature (Merge requests)
        if project.merge_requests_enabled \
                and GitLabFeature.Features.MERGE_REQUESTS in features:
            project.merge_requests_access_level = GitLabFeature.AccessLevels.DISABLED
            project.merge_requests_enabled = False
            result += [GitLabFeature.Features.MERGE_REQUESTS]

        # Disable feature (Forks)
        if project.forking_access_level != GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.FORKS in features:
            project.forking_access_level = GitLabFeature.AccessLevels.DISABLED
            result += [GitLabFeature.Features.FORKS]

        # Disable feature (Git LFS)
        if project.lfs_enabled \
                and GitLabFeature.Features.GIT_LFS in features:
            project.lfs_enabled = False
            result += [GitLabFeature.Features.GIT_LFS]

        # Disable feature (CI/CD)
        if project.jobs_enabled \
                and GitLabFeature.Features.CI_CD in features:
            project.builds_access_level = GitLabFeature.AccessLevels.DISABLED
            project.jobs_enabled = False
            result += [GitLabFeature.Features.CI_CD]

        # Disable feature (Repository)
        if project.repository_access_level != GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.REPOSITORY in features:
            project.repository_access_level = GitLabFeature.AccessLevels.DISABLED
            project.merge_requests_access_level = GitLabFeature.AccessLevels.DISABLED
            project.merge_requests_enabled = False
            project.forking_access_level = GitLabFeature.AccessLevels.DISABLED
            project.lfs_enabled = False
            project.builds_access_level = GitLabFeature.AccessLevels.DISABLED
            project.jobs_enabled = False
            result += [GitLabFeature.Features.REPOSITORY]

        # Disable feature (Container registry)
        if project.container_registry_enabled \
                and GitLabFeature.Features.CONTAINER_REGISTRY in features:
            project.container_registry_access_level = GitLabFeature.AccessLevels.DISABLED
            project.container_registry_enabled = False
            result += [GitLabFeature.Features.CONTAINER_REGISTRY]

        # Disable feature (Analytics)
        if project.analytics_access_level != GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.ANALYTICS in features:
            project.analytics_access_level = GitLabFeature.AccessLevels.DISABLED
            result += [GitLabFeature.Features.ANALYTICS]

        # Disable feature (Security and Compliance)
        if project.security_and_compliance_access_level != GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.SECURITY_AND_COMPLIANCE in features:
            project.security_and_compliance_access_level = GitLabFeature.AccessLevels.DISABLED
            result += [GitLabFeature.Features.SECURITY_AND_COMPLIANCE]

        # Disable feature (Wiki)
        if project.wiki_enabled \
                and GitLabFeature.Features.WIKI in features:
            project.wiki_access_level = GitLabFeature.AccessLevels.DISABLED
            project.wiki_enabled = False
            result += [GitLabFeature.Features.WIKI]

        # Disable feature (Snippets)
        if project.snippets_enabled \
                and GitLabFeature.Features.SNIPPETS in features:
            project.snippets_access_level = GitLabFeature.AccessLevels.DISABLED
            project.snippets_enabled = False
            result += [GitLabFeature.Features.SNIPPETS]

        # Disable feature (Package registry)
        if project.packages_enabled \
                and GitLabFeature.Features.PACKAGE_REGISTRY in features:
            project.packages_enabled = False
            result += [GitLabFeature.Features.PACKAGE_REGISTRY]

        # Disable feature (Model experiments)
        if project.model_experiments_access_level != GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.MODEL_EXPERIMENTS in features:
            project.model_experiments_access_level = GitLabFeature.AccessLevels.DISABLED
            result += [GitLabFeature.Features.MODEL_EXPERIMENTS]

        # Disable feature (Model registry)
        if project.model_registry_access_level != GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.MODEL_REGISTRY in features:
            project.model_registry_access_level = GitLabFeature.AccessLevels.DISABLED
            result += [GitLabFeature.Features.MODEL_REGISTRY]

        # Disable feature (Pages)
        if project.pages_access_level != GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.PAGES in features:
            project.pages_access_level = GitLabFeature.AccessLevels.DISABLED
            result += [GitLabFeature.Features.PAGES]

        # Disable feature (Monitor)
        if project.monitor_access_level != GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.MONITOR in features:
            project.monitor_access_level = GitLabFeature.AccessLevels.DISABLED
            result += [GitLabFeature.Features.MONITOR]

        # Disable feature (Environments)
        if project.environments_access_level != GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.ENVIRONMENTS in features:
            project.environments_access_level = GitLabFeature.AccessLevels.DISABLED
            result += [GitLabFeature.Features.ENVIRONMENTS]

        # Disable feature (Feature flags)
        if project.feature_flags_access_level != GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.FEATURE_FLAGS in features:
            project.feature_flags_access_level = GitLabFeature.AccessLevels.DISABLED
            result += [GitLabFeature.Features.FEATURE_FLAGS]

        # Disable feature (Infrastructure)
        if project.infrastructure_access_level != GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.INFRASTRUCTURE in features:
            project.infrastructure_access_level = GitLabFeature.AccessLevels.DISABLED
            result += [GitLabFeature.Features.INFRASTRUCTURE]

        # Disable feature (Releases)
        if project.releases_access_level != GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.RELEASES in features:
            project.releases_access_level = GitLabFeature.AccessLevels.DISABLED
            result += [GitLabFeature.Features.RELEASES]

        # Disable feature (Service Desk)
        if project.service_desk_enabled \
                and GitLabFeature.Features.SERVICE_DESK in features:
            project.service_desk_enabled = False
            result += [GitLabFeature.Features.SERVICE_DESK]

        # Disable feature (Auto DevOps)
        if project.auto_devops_enabled \
                and GitLabFeature.Features.AUTO_DEVOPS in features:
            project.auto_devops_enabled = False
            result += [GitLabFeature.Features.AUTO_DEVOPS]

        # Save project
        if not self.__dry_run:
            project.save()

        # Result
        return result

    # Project enable features, pylint: disable=too-many-branches,too-many-statements
    def project_features_enable(
        self,
        criteria: str,
        features: List[str],
    ) -> List[str]:

        # Variables
        result: List[str] = []
        project = self.__gitlab.projects.get(criteria, statistics=True)

        # Enable feature (Issues)
        if not project.issues_enabled \
                and GitLabFeature.Features.ISSUES in features:
            if project.visibility == GitLabFeature.Visibility.PRIVATE:
                project.issues_access_level = GitLabFeature.AccessLevels.PRIVATE
            else:
                project.issues_access_level = GitLabFeature.AccessLevels.ENABLED
            project.issues_enabled = True
            result += [GitLabFeature.Features.ISSUES]

        # Enable feature (Merge requests)
        if not project.merge_requests_enabled \
                and GitLabFeature.Features.MERGE_REQUESTS in features:
            if project.visibility == GitLabFeature.Visibility.PRIVATE:
                project.merge_requests_access_level = GitLabFeature.AccessLevels.PRIVATE
            else:
                project.merge_requests_access_level = GitLabFeature.AccessLevels.ENABLED
            project.merge_requests_enabled = True
            result += [GitLabFeature.Features.MERGE_REQUESTS]

        # Enable feature (Forks)
        if project.forking_access_level == GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.FORKS in features:
            if project.visibility == GitLabFeature.Visibility.PRIVATE:
                project.forking_access_level = GitLabFeature.AccessLevels.PRIVATE
            else:
                project.forking_access_level = GitLabFeature.AccessLevels.ENABLED
            result += [GitLabFeature.Features.FORKS]

        # Enable feature (Git LFS)
        if not project.lfs_enabled \
                and GitLabFeature.Features.GIT_LFS in features:
            project.lfs_enabled = True
            result += [GitLabFeature.Features.GIT_LFS]

        # Enable feature (CI/CD)
        if not project.jobs_enabled \
                and GitLabFeature.Features.CI_CD in features:
            if project.visibility == GitLabFeature.Visibility.PRIVATE:
                project.builds_access_level = GitLabFeature.AccessLevels.PRIVATE
            else:
                project.builds_access_level = GitLabFeature.AccessLevels.ENABLED
            project.jobs_enabled = True
            result += [GitLabFeature.Features.CI_CD]

        # Enable feature (Repository)
        if project.repository_access_level == GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.REPOSITORY in features:
            project.repository_access_level = GitLabFeature.AccessLevels.ENABLED
            result += [GitLabFeature.Features.REPOSITORY]

        # Enable feature (Container registry)
        if not project.container_registry_enabled \
                and GitLabFeature.Features.CONTAINER_REGISTRY in features:
            if project.visibility == GitLabFeature.Visibility.PRIVATE:
                project.container_registry_access_level = GitLabFeature.AccessLevels.PRIVATE
            else:
                project.container_registry_access_level = GitLabFeature.AccessLevels.ENABLED
            project.container_registry_enabled = True
            result += [GitLabFeature.Features.CONTAINER_REGISTRY]

        # Enable feature (Analytics)
        if project.analytics_access_level == GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.ANALYTICS in features:
            if project.visibility == GitLabFeature.Visibility.PRIVATE:
                project.analytics_access_level = GitLabFeature.AccessLevels.PRIVATE
            else:
                project.analytics_access_level = GitLabFeature.AccessLevels.ENABLED
            result += [GitLabFeature.Features.ANALYTICS]

        # Enable feature (Security and Compliance)
        if project.security_and_compliance_access_level == GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.SECURITY_AND_COMPLIANCE in features:
            project.security_and_compliance_access_level = GitLabFeature.AccessLevels.PRIVATE
            result += [GitLabFeature.Features.SECURITY_AND_COMPLIANCE]

        # Enable feature (Wiki)
        if not project.wiki_enabled \
                and GitLabFeature.Features.WIKI in features:
            if project.visibility == GitLabFeature.Visibility.PRIVATE:
                project.wiki_access_level = GitLabFeature.AccessLevels.PRIVATE
            else:
                project.wiki_access_level = GitLabFeature.AccessLevels.ENABLED
            project.wiki_enabled = True
            result += [GitLabFeature.Features.WIKI]

        # Enable feature (Snippets)
        if not project.snippets_enabled \
                and GitLabFeature.Features.SNIPPETS in features:
            if project.visibility == GitLabFeature.Visibility.PRIVATE:
                project.snippets_access_level = GitLabFeature.AccessLevels.PRIVATE
            else:
                project.snippets_access_level = GitLabFeature.AccessLevels.ENABLED
            project.snippets_enabled = True
            result += [GitLabFeature.Features.SNIPPETS]

        # Enable feature (Package registry)
        if not project.packages_enabled \
                and GitLabFeature.Features.PACKAGE_REGISTRY in features:
            project.packages_enabled = True
            result += [GitLabFeature.Features.PACKAGE_REGISTRY]

        # Enable feature (Model experiments)
        if project.model_experiments_access_level == GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.MODEL_EXPERIMENTS in features:
            if project.visibility == GitLabFeature.Visibility.PRIVATE:
                project.model_experiments_access_level = GitLabFeature.AccessLevels.PRIVATE
            else:
                project.model_experiments_access_level = GitLabFeature.AccessLevels.ENABLED
            result += [GitLabFeature.Features.MODEL_EXPERIMENTS]

        # Enable feature (Model registry)
        if project.model_registry_access_level == GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.MODEL_REGISTRY in features:
            if project.visibility == GitLabFeature.Visibility.PRIVATE:
                project.model_registry_access_level = GitLabFeature.AccessLevels.PRIVATE
            else:
                project.model_registry_access_level = GitLabFeature.AccessLevels.ENABLED
            result += [GitLabFeature.Features.MODEL_REGISTRY]

        # Enable feature (Pages)
        if project.pages_access_level == GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.PAGES in features:
            if project.visibility == GitLabFeature.Visibility.PUBLIC:
                project.pages_access_level = GitLabFeature.AccessLevels.ENABLED
            else:
                project.pages_access_level = GitLabFeature.AccessLevels.PRIVATE
            result += [GitLabFeature.Features.PAGES]

        # Enable feature (Monitor)
        if project.monitor_access_level == GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.MONITOR in features:
            if project.visibility == GitLabFeature.Visibility.PRIVATE:
                project.monitor_access_level = GitLabFeature.AccessLevels.PRIVATE
            else:
                project.monitor_access_level = GitLabFeature.AccessLevels.ENABLED
            result += [GitLabFeature.Features.MONITOR]

        # Enable feature (Environments)
        if project.environments_access_level == GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.ENVIRONMENTS in features:
            if project.visibility == GitLabFeature.Visibility.PRIVATE:
                project.environments_access_level = GitLabFeature.AccessLevels.PRIVATE
            else:
                project.environments_access_level = GitLabFeature.AccessLevels.ENABLED
            result += [GitLabFeature.Features.ENVIRONMENTS]

        # Enable feature (Feature flags)
        if project.feature_flags_access_level == GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.FEATURE_FLAGS in features:
            if project.visibility == GitLabFeature.Visibility.PRIVATE:
                project.feature_flags_access_level = GitLabFeature.AccessLevels.PRIVATE
            else:
                project.feature_flags_access_level = GitLabFeature.AccessLevels.ENABLED
            result += [GitLabFeature.Features.FEATURE_FLAGS]

        # Enable feature (Infrastructure)
        if project.infrastructure_access_level == GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.INFRASTRUCTURE in features:
            if project.visibility == GitLabFeature.Visibility.PRIVATE:
                project.infrastructure_access_level = GitLabFeature.AccessLevels.PRIVATE
            else:
                project.infrastructure_access_level = GitLabFeature.AccessLevels.ENABLED
            result += [GitLabFeature.Features.INFRASTRUCTURE]

        # Enable feature (Releases)
        if project.releases_access_level == GitLabFeature.AccessLevels.DISABLED \
                and GitLabFeature.Features.RELEASES in features:
            if project.visibility == GitLabFeature.Visibility.PRIVATE:
                project.releases_access_level = GitLabFeature.AccessLevels.PRIVATE
            else:
                project.releases_access_level = GitLabFeature.AccessLevels.ENABLED
            result += [GitLabFeature.Features.RELEASES]

        # Enable feature (Service Desk)
        if not project.service_desk_enabled \
                and GitLabFeature.Features.SERVICE_DESK in features:
            project.service_desk_enabled = True
            result += [GitLabFeature.Features.SERVICE_DESK]

        # Enable feature (Auto DevOps)
        if not project.auto_devops_enabled \
                and GitLabFeature.Features.AUTO_DEVOPS in features:
            project.auto_devops_enabled = True
            result += [GitLabFeature.Features.AUTO_DEVOPS]

        # Save project
        if not self.__dry_run:
            project.save()

        # Result
        return result

    # Project protect tags, pylint: disable=too-many-branches
    def project_protect_tags(self, criteria: str, protect_level: str) -> List[str]: